diff --git a/archived/ml_aci/.github/img_01.png b/archived/ml_aci/.github/img_01.png
new file mode 100644
index 0000000..decfe41
Binary files /dev/null and b/archived/ml_aci/.github/img_01.png differ
diff --git a/archived/ml_aci/Main.cs b/archived/ml_aci/Main.cs
new file mode 100644
index 0000000..cc8711a
--- /dev/null
+++ b/archived/ml_aci/Main.cs
@@ -0,0 +1,58 @@
+using ABI_RC.Core.EventSystem;
+using ABI_RC.Core.InteractionSystem;
+using ABI_RC.Core.Networking;
+using ABI_RC.Core.Util;
+using DarkRift;
+using System.Reflection;
+
+namespace ml_aci
+{
+ public class AvatarChangeInfo : MelonLoader.MelonMod
+ {
+ public override void OnInitializeMelon()
+ {
+ HarmonyInstance.Patch(
+ typeof(AssetManagement).GetMethod(nameof(AssetManagement.LoadLocalAvatar)),
+ null,
+ new HarmonyLib.HarmonyMethod(typeof(AvatarChangeInfo).GetMethod(nameof(OnLocalAvatarLoad), BindingFlags.NonPublic | BindingFlags.Static))
+ );
+
+ HarmonyInstance.Patch(
+ typeof(CVRSyncHelper).GetMethod(nameof(CVRSyncHelper.SpawnProp)),
+ null,
+ new HarmonyLib.HarmonyMethod(typeof(AvatarChangeInfo).GetMethod(nameof(OnPropSpawned), BindingFlags.NonPublic | BindingFlags.Static))
+ );
+ }
+
+ static void OnLocalAvatarLoad()
+ {
+ try
+ {
+ if(ViewManager.Instance != null)
+ ViewManager.Instance.TriggerPushNotification("Avatar changed", 1f);
+ }
+ catch(System.Exception e)
+ {
+ MelonLoader.MelonLogger.Error(e);
+ }
+ }
+
+ static void OnPropSpawned()
+ {
+ try
+ {
+ if(ViewManager.Instance != null)
+ {
+ if((NetworkManager.Instance != null) && (NetworkManager.Instance.GameNetwork.ConnectionState == ConnectionState.Connected))
+ ViewManager.Instance.TriggerPushNotification("Prop spawned", 1f);
+ else
+ ViewManager.Instance.TriggerAlert("Prop Error", "Not connected to live instance", -1, true);
+ }
+ }
+ catch(System.Exception e)
+ {
+ MelonLoader.MelonLogger.Error(e);
+ }
+ }
+ }
+}
diff --git a/archived/ml_aci/Properties/AssemblyInfo.cs b/archived/ml_aci/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..fbd14c8
--- /dev/null
+++ b/archived/ml_aci/Properties/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Reflection;
+
+[assembly: AssemblyTitle("AvatarChangeInfo")]
+[assembly: AssemblyVersion("1.0.3")]
+[assembly: AssemblyFileVersion("1.0.3")]
+
+[assembly: MelonLoader.MelonInfo(typeof(ml_aci.AvatarChangeInfo), "AvatarChangeInfo", "1.0.3", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
+[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
+[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
+[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
\ No newline at end of file
diff --git a/archived/ml_aci/README.md b/archived/ml_aci/README.md
new file mode 100644
index 0000000..fba8935
--- /dev/null
+++ b/archived/ml_aci/README.md
@@ -0,0 +1,9 @@
+# Avatar Change Info
+This mod shows simple main menu popup upon local player avatar change and prop spawn.
+
+
+
+# Installation
+* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader)
+* Get [latest release DLL](../../../releases/latest):
+ * Put `ml_aci.dll` in `Mods` folder of game
diff --git a/archived/ml_aci/ml_aci.csproj b/archived/ml_aci/ml_aci.csproj
new file mode 100644
index 0000000..25e1641
--- /dev/null
+++ b/archived/ml_aci/ml_aci.csproj
@@ -0,0 +1,77 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {1B5ACA07-6266-4C9A-BA30-D4BBE6634846}
+ Library
+ Properties
+ ml_aci
+ ml_aci
+ v4.7.2
+ 512
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+
+ False
+ F:\games\Steam\common\ChilloutVR\MelonLoader\0Harmony.dll
+ False
+
+
+ False
+ F:\games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll
+ False
+
+
+ False
+
+
+ False
+ F:\games\Steam\common\ChilloutVR\MelonLoader\MelonLoader.dll
+ False
+
+
+
+
+
+
+
+
+
+ False
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+ copy /y "$(TargetPath)" "C:\Games\Steam\common\ChilloutVR\Mods\"
+
+
\ No newline at end of file
diff --git a/archived/ml_aci/ml_aci.csproj.user b/archived/ml_aci/ml_aci.csproj.user
new file mode 100644
index 0000000..2539084
--- /dev/null
+++ b/archived/ml_aci/ml_aci.csproj.user
@@ -0,0 +1,6 @@
+
+
+
+ C:\Games\Steam\common\ChilloutVR\MelonLoader\;C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\
+
+
\ No newline at end of file
diff --git a/archived/ml_fpt/Main.cs b/archived/ml_fpt/Main.cs
new file mode 100644
index 0000000..f748e3a
--- /dev/null
+++ b/archived/ml_fpt/Main.cs
@@ -0,0 +1,313 @@
+using ABI.CCK.Scripts;
+using ABI_RC.Core.InteractionSystem;
+using ABI_RC.Core.Player;
+using ABI_RC.Core.Savior;
+using ABI_RC.Core.UI;
+using ABI_RC.Systems.IK;
+using ABI_RC.Systems.IK.SubSystems;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEngine;
+
+namespace ml_fpt
+{
+ public class FourPointTracking : MelonLoader.MelonMod
+ {
+ static FourPointTracking ms_instance = null;
+
+ bool m_ready = false;
+
+ IndexIK m_indexIK = null;
+ RootMotion.FinalIK.VRIK m_vrIK = null;
+ RuntimeAnimatorController m_runtimeAnimator = null;
+ List m_aasParameters = null;
+
+ bool m_calibrationActive = false;
+ object m_calibrationTask = null;
+
+ int m_hipsTrackerIndex = -1;
+ Transform m_hips = null;
+
+ Dictionary> m_avatarCalibrations = null;
+
+ public override void OnInitializeMelon()
+ {
+ if(ms_instance == null)
+ ms_instance = this;
+
+ m_avatarCalibrations = new Dictionary>();
+
+ HarmonyInstance.Patch(
+ typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.ClearAvatar)),
+ null,
+ new HarmonyLib.HarmonyMethod(typeof(FourPointTracking).GetMethod(nameof(OnAvatarClear_Postfix), BindingFlags.NonPublic | BindingFlags.Static))
+ );
+ HarmonyInstance.Patch(
+ typeof(PlayerSetup).GetMethod(nameof(PlayerSetup.SetupAvatar)),
+ null,
+ new HarmonyLib.HarmonyMethod(typeof(FourPointTracking).GetMethod(nameof(OnSetupAvatar_Postfix), BindingFlags.Static | BindingFlags.NonPublic))
+ );
+
+ MelonLoader.MelonCoroutines.Start(WaitForMainMenuView());
+ MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer());
+ }
+
+ System.Collections.IEnumerator WaitForMainMenuView()
+ {
+ while(ViewManager.Instance == null)
+ yield return null;
+ while(ViewManager.Instance.gameMenuView == null)
+ yield return null;
+ while(ViewManager.Instance.gameMenuView.Listener == null)
+ yield return null;
+
+ ViewManager.Instance.gameMenuView.Listener.ReadyForBindings += () =>
+ {
+ ViewManager.Instance.gameMenuView.View.RegisterForEvent("MelonMod_FPT_Action_Calibrate", new Action(this.StartCalibration));
+ };
+
+ ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
+ {
+ ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("menu.js"));
+ };
+ }
+
+ System.Collections.IEnumerator WaitForLocalPlayer()
+ {
+ while(PlayerSetup.Instance == null)
+ yield return null;
+
+ m_indexIK = PlayerSetup.Instance.gameObject.GetComponent();
+
+ m_ready = true;
+ }
+
+ public override void OnDeinitializeMelon()
+ {
+ if(ms_instance == this)
+ ms_instance = null;
+
+ m_ready = false;
+ m_aasParameters?.Clear();
+ m_aasParameters = null;
+ m_avatarCalibrations?.Clear();
+ m_avatarCalibrations = null;
+ m_hipsTrackerIndex = -1;
+
+ if(m_calibrationTask != null)
+ MelonLoader.MelonCoroutines.Stop(m_calibrationTask);
+ m_calibrationTask = null;
+ }
+
+ void StartCalibration()
+ {
+ if(m_ready && !m_calibrationActive && PlayerSetup.Instance._inVr && !PlayerSetup.Instance.avatarIsLoading && PlayerSetup.Instance._animator.isHuman && !BodySystem.isCalibrating && !BodySystem.isCalibratedAsFullBody)
+ {
+ m_hipsTrackerIndex = GetHipsTracker();
+ if(m_hipsTrackerIndex != -1)
+ {
+ m_avatarCalibrations.Remove(MetaPort.Instance.currentAvatarGuid);
+
+ m_runtimeAnimator = PlayerSetup.Instance._animator.runtimeAnimatorController;
+ m_aasParameters = PlayerSetup.Instance.animatorManager.GetAdditionalSettingsCurrent();
+ PlayerSetup.Instance._animator.runtimeAnimatorController = PlayerSetup.Instance.tPoseAnimatorController;
+ PlayerSetup.Instance.animatorManager.SetAnimator(PlayerSetup.Instance._animator, PlayerSetup.Instance.tPoseAnimatorController);
+
+ m_hips = PlayerSetup.Instance._animator.GetBoneTransform(HumanBodyBones.Hips);
+ m_vrIK = PlayerSetup.Instance._animator.GetComponent();
+
+ if(m_vrIK != null)
+ m_vrIK.solver.OnPreUpdate += this.OverrideIKWeight;
+
+ IKSystem.Instance.leftHandModel.SetActive(true);
+ IKSystem.Instance.rightHandModel.SetActive(true);
+ PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowTracker(true);
+ CVR_InteractableManager.enableInteractions = false;
+
+ m_calibrationActive = true;
+ m_calibrationTask = MelonLoader.MelonCoroutines.Start(CalibrationTask());
+
+ ViewManager.Instance.ForceUiStatus(false);
+ ShowHudNotification("Calibration started");
+ }
+ else
+ ShowMenuAlert("No hips tracker detected. Check if tracker has waist role in SteamVR settings.");
+ }
+ else
+ ShowMenuAlert("Calibraton requirements aren't met: be in VR, be not in FBT or avatar calibration, humanoid avatar");
+ }
+
+ System.Collections.IEnumerator CalibrationTask()
+ {
+ while(m_calibrationActive)
+ {
+ if(m_vrIK != null)
+ m_vrIK.enabled = false;
+
+ m_indexIK.enabled = false;
+
+ PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowLine(true, m_hips);
+
+ if((CVRInputManager.Instance.interactLeftValue > 0.9f) && (CVRInputManager.Instance.interactRightValue > 0.9f))
+ {
+ PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target.transform.position = m_hips.position;
+ PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target.transform.rotation = m_hips.rotation;
+
+ m_avatarCalibrations.Add(
+ MetaPort.Instance.currentAvatarGuid,
+ new Tuple(
+ PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target.transform.localPosition,
+ PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target.transform.localRotation
+ )
+ );
+
+ if(m_vrIK != null)
+ {
+ m_vrIK.solver.spine.pelvisTarget = PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].target;
+ m_vrIK.solver.spine.pelvisPositionWeight = 1f;
+ m_vrIK.solver.spine.pelvisRotationWeight = 1f;
+ m_vrIK.solver.OnPreUpdate -= this.OverrideIKWeight;
+ m_vrIK.solver.IKPositionWeight = 1f;
+ m_vrIK.enabled = true;
+ }
+
+ m_indexIK.enabled = true;
+
+ PlayerSetup.Instance._animator.runtimeAnimatorController = m_runtimeAnimator;
+ PlayerSetup.Instance.animatorManager.SetAnimator(PlayerSetup.Instance._animator, m_runtimeAnimator);
+ if(m_aasParameters != null)
+ {
+ foreach(var l_param in m_aasParameters)
+ {
+ PlayerSetup.Instance.animatorManager.SetAnimatorParameter(l_param.name, l_param.value);
+ }
+ }
+
+ IKSystem.Instance.leftHandModel.SetActive(false);
+ IKSystem.Instance.rightHandModel.SetActive(false);
+ PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowTracker(false);
+ PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowLine(false);
+ CVR_InteractableManager.enableInteractions = true;
+
+ Reset();
+
+ ShowHudNotification("Calibration completed");
+ }
+
+ yield return null;
+ }
+
+ m_calibrationTask = null; // Idk if it's safe or not
+ }
+
+ void OverrideIKWeight()
+ {
+ if(m_calibrationActive)
+ {
+ m_vrIK.solver.IKPositionWeight = 0f;
+ }
+ }
+
+ void Reset()
+ {
+ m_vrIK = null;
+ m_runtimeAnimator = null;
+ m_aasParameters = null;
+ m_calibrationActive = false;
+ m_calibrationTask = null;
+ m_hipsTrackerIndex = -1;
+ m_hips = null;
+ }
+
+ static void OnAvatarClear_Postfix() => ms_instance?.OnAvatarClear();
+ void OnAvatarClear()
+ {
+ try
+ {
+ if(m_calibrationActive)
+ {
+ if(m_calibrationTask != null)
+ MelonLoader.MelonCoroutines.Stop(m_calibrationTask);
+
+ m_indexIK.enabled = true;
+
+ IKSystem.Instance.leftHandModel.SetActive(false);
+ IKSystem.Instance.rightHandModel.SetActive(false);
+
+ if(m_hipsTrackerIndex != -1)
+ {
+ PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowTracker(false);
+ PlayerSetup.Instance._trackerManager.trackers[m_hipsTrackerIndex].ShowLine(false);
+ }
+ CVR_InteractableManager.enableInteractions = true;
+
+ Reset();
+
+ ShowHudNotification("Calibration canceled");
+ }
+ }
+ catch(Exception e)
+ {
+ MelonLoader.MelonLogger.Error(e);
+ }
+ }
+
+ static void OnSetupAvatar_Postfix() => ms_instance?.OnSetupAvatar();
+ void OnSetupAvatar()
+ {
+ try
+ {
+ if(m_ready && PlayerSetup.Instance._inVr && PlayerSetup.Instance._animator.isHuman && !VRTrackerManager.Instance.CheckFullBody())
+ {
+ int l_hipsTracker = GetHipsTracker();
+ if((l_hipsTracker != -1) && m_avatarCalibrations.TryGetValue(MetaPort.Instance.currentAvatarGuid, out var l_stored))
+ {
+ var l_vrIK = PlayerSetup.Instance._animator.GetComponent();
+ if(l_vrIK != null)
+ {
+ l_vrIK.solver.spine.pelvisTarget = PlayerSetup.Instance._trackerManager.trackers[l_hipsTracker].target;
+ l_vrIK.solver.spine.pelvisPositionWeight = 1f;
+ l_vrIK.solver.spine.pelvisRotationWeight = 1f;
+
+ l_vrIK.solver.spine.pelvisTarget.localPosition = l_stored.Item1;
+ l_vrIK.solver.spine.pelvisTarget.localRotation = l_stored.Item2;
+
+ ShowHudNotification("Applied saved calibration");
+ }
+ }
+ }
+ }
+ catch(System.Exception e)
+ {
+ MelonLoader.MelonLogger.Error(e);
+ }
+ }
+
+ static void ShowHudNotification(string p_message)
+ {
+ if(CohtmlHud.Instance != null)
+ CohtmlHud.Instance.ViewDropText("4-Point Tracking", p_message);
+ }
+
+ static void ShowMenuAlert(string p_message)
+ {
+ if(ViewManager.Instance != null)
+ ViewManager.Instance.TriggerAlert("4-Point Tracking", p_message, 0, false);
+ }
+
+ static int GetHipsTracker()
+ {
+ int l_result = -1;
+ for(int i = 0; i < PlayerSetup.Instance._trackerManager.trackerNames.Length; i++)
+ {
+ if((PlayerSetup.Instance._trackerManager.trackerNames[i] == "vive_tracker_waist") && PlayerSetup.Instance._trackerManager.trackers[i].active)
+ {
+ l_result = i;
+ break;
+ }
+ }
+ return l_result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/archived/ml_fpt/Properties/AssemblyInfo.cs b/archived/ml_fpt/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..388da0e
--- /dev/null
+++ b/archived/ml_fpt/Properties/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Reflection;
+
+[assembly: AssemblyTitle("FourPointTracking")]
+[assembly: AssemblyVersion("1.0.9")]
+[assembly: AssemblyFileVersion("1.0.9")]
+
+[assembly: MelonLoader.MelonInfo(typeof(ml_fpt.FourPointTracking), "FourPointTracking", "1.0.9", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
+[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
+[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
+[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
\ No newline at end of file
diff --git a/archived/ml_fpt/README.md b/archived/ml_fpt/README.md
new file mode 100644
index 0000000..8eaeeb7
--- /dev/null
+++ b/archived/ml_fpt/README.md
@@ -0,0 +1,18 @@
+# Four Point Tracking
+This mod adds ability to use 4-point tracking.
+
+# Installation
+* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader)
+* Get [latest release DLL](../../../releases/latest):
+ * Put `ml_fpt.dll` in `Mods` folder of game
+
+# Usage
+* Be sure that your tracker role is set to `Hips` in SteamVR
+* Go to `Settings - Implementation - 4-Point Tracking` and press `Calibrate` button
+* Adjust your tracker in a similar way as in FBT calibration
+* Press trigger on both controllers
+
+# Notes
+* Will be deprecated soon
+* Calibration is saved per avatar for game session.
+* AAS parameters are restored after calibration.
diff --git a/archived/ml_fpt/Scripts.cs b/archived/ml_fpt/Scripts.cs
new file mode 100644
index 0000000..a0b5f81
--- /dev/null
+++ b/archived/ml_fpt/Scripts.cs
@@ -0,0 +1,26 @@
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace ml_fpt
+{
+ static class Scripts
+ {
+ public static string GetEmbeddedScript(string p_name)
+ {
+ string l_result = "";
+ Assembly l_assembly = Assembly.GetExecutingAssembly();
+ string l_assemblyName = l_assembly.GetName().Name;
+
+ try
+ {
+ Stream l_libraryStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + p_name);
+ StreamReader l_streadReader = new StreamReader(l_libraryStream);
+ l_result = l_streadReader.ReadToEnd();
+ }
+ catch(Exception) { }
+
+ return l_result;
+ }
+ }
+}
diff --git a/archived/ml_fpt/ml_fpt.csproj b/archived/ml_fpt/ml_fpt.csproj
new file mode 100644
index 0000000..77ebda4
--- /dev/null
+++ b/archived/ml_fpt/ml_fpt.csproj
@@ -0,0 +1,88 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {EC0A8C41-A429-42CD-B8FA-401A802D4BA6}
+ Library
+ Properties
+ ml_fpt
+ ml_fpt
+ v4.7.2
+ 512
+ true
+
+
+
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+
+ False
+
+
+ C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll
+ False
+
+
+ False
+ C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp-firstpass.dll
+ False
+
+
+ C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\cohtml.Net.dll
+ False
+
+
+ C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\Cohtml.Runtime.dll
+ False
+
+
+ C:\Games\Steam\common\ChilloutVR\MelonLoader\MelonLoader.dll
+ False
+
+
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+ copy /y "$(TargetPath)" "C:\Games\Steam\common\ChilloutVR\Mods\
+
+
\ No newline at end of file
diff --git a/archived/ml_fpt/ml_fpt.csproj.user b/archived/ml_fpt/ml_fpt.csproj.user
new file mode 100644
index 0000000..2539084
--- /dev/null
+++ b/archived/ml_fpt/ml_fpt.csproj.user
@@ -0,0 +1,6 @@
+
+
+
+ C:\Games\Steam\common\ChilloutVR\MelonLoader\;C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\
+
+
\ No newline at end of file
diff --git a/archived/ml_fpt/resources/menu.js b/archived/ml_fpt/resources/menu.js
new file mode 100644
index 0000000..ee02114
--- /dev/null
+++ b/archived/ml_fpt/resources/menu.js
@@ -0,0 +1,12 @@
+{
+ let l_block = document.createElement('div');
+ l_block.innerHTML = `
+
+
+
+ `;
+ document.getElementById('settings-implementation').appendChild(l_block);
+}
\ No newline at end of file
diff --git a/archived/ml_sci/.github/img_01.png b/archived/ml_sci/.github/img_01.png
new file mode 100644
index 0000000..1d32654
Binary files /dev/null and b/archived/ml_sci/.github/img_01.png differ
diff --git a/archived/ml_sci/Main.cs b/archived/ml_sci/Main.cs
new file mode 100644
index 0000000..7aa4468
--- /dev/null
+++ b/archived/ml_sci/Main.cs
@@ -0,0 +1,31 @@
+using ABI_RC.Core.UI;
+using DarkRift.Client;
+using System.Reflection;
+
+namespace ml_sci
+{
+ public class ServerConnectionInfo : MelonLoader.MelonMod
+ {
+ public override void OnInitializeMelon()
+ {
+ HarmonyInstance.Patch(
+ typeof(ABI_RC.Core.Networking.NetworkManager).GetMethod("OnGameNetworkConnectionClosed", BindingFlags.NonPublic | BindingFlags.Instance),
+ null,
+ new HarmonyLib.HarmonyMethod(typeof(ServerConnectionInfo).GetMethod(nameof(OnGameNetworkConnectionClosed), BindingFlags.NonPublic | BindingFlags.Static))
+ );
+ }
+
+ static void OnGameNetworkConnectionClosed(object __0, DisconnectedEventArgs __1)
+ {
+ try
+ {
+ if((CohtmlHud.Instance != null) && (__1 != null) && (!__1.LocalDisconnect))
+ CohtmlHud.Instance.ViewDropTextImmediate("(Local) Client", "Connection lost", (__1.Error != System.Net.Sockets.SocketError.Success) ? ("Reason: " + __1.Error.ToString()) : "");
+ }
+ catch(System.Exception e)
+ {
+ MelonLoader.MelonLogger.Error(e);
+ }
+ }
+ }
+}
diff --git a/archived/ml_sci/Properties/AssemblyInfo.cs b/archived/ml_sci/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c15c663
--- /dev/null
+++ b/archived/ml_sci/Properties/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Reflection;
+
+[assembly: AssemblyTitle("ServerConnectionInfo")]
+[assembly: AssemblyVersion("1.0.2")]
+[assembly: AssemblyFileVersion("1.0.2")]
+
+[assembly: MelonLoader.MelonInfo(typeof(ml_sci.ServerConnectionInfo), "ServerConnectionInfo", "1.0.2", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
+[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
+[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
+[assembly: MelonLoader.MelonPlatformDomain(MelonLoader.MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
\ No newline at end of file
diff --git a/archived/ml_sci/README.md b/archived/ml_sci/README.md
new file mode 100644
index 0000000..452a888
--- /dev/null
+++ b/archived/ml_sci/README.md
@@ -0,0 +1,9 @@
+# Server Connection Info
+This mod shows HUD notification upon server disconnection.
+
+
+
+# Installation
+* Install [latest MelonLoader](https://github.com/LavaGang/MelonLoader)
+* Get [latest release DLL](../../../releases/latest):
+ * Put `ml_sci.dll` in `Mods` folder of game
diff --git a/archived/ml_sci/ml_sci.csproj b/archived/ml_sci/ml_sci.csproj
new file mode 100644
index 0000000..1e71c50
--- /dev/null
+++ b/archived/ml_sci/ml_sci.csproj
@@ -0,0 +1,79 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {E5481D41-196C-4241-AF26-6595EF1863C1}
+ Library
+ Properties
+ ml_sci
+ ml_sci
+ v4.7.2
+ 512
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE
+ full
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+ bin\x64\Release\
+ TRACE
+ true
+ pdbonly
+ x64
+ prompt
+ MinimumRecommendedRules.ruleset
+
+
+
+ False
+ F:\games\Steam\common\ChilloutVR\MelonLoader\0Harmony.dll
+ False
+
+
+ False
+ F:\games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\Assembly-CSharp.dll
+ False
+
+
+ False
+ C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\DarkRift.Client.dll
+ False
+
+
+ False
+ F:\games\Steam\common\ChilloutVR\MelonLoader\MelonLoader.dll
+ False
+
+
+
+
+
+
+
+
+
+ False
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+ copy /y "$(TargetPath)" "C:\Games\Steam\common\ChilloutVR\Mods\"
+
+
\ No newline at end of file
diff --git a/archived/ml_sci/ml_sci.csproj.user b/archived/ml_sci/ml_sci.csproj.user
new file mode 100644
index 0000000..2539084
--- /dev/null
+++ b/archived/ml_sci/ml_sci.csproj.user
@@ -0,0 +1,6 @@
+
+
+
+ C:\Games\Steam\common\ChilloutVR\MelonLoader\;C:\Games\Steam\common\ChilloutVR\ChilloutVR_Data\Managed\
+
+
\ No newline at end of file