├── AvatarSdkPatcher.cs ├── README.md ├── SdkPatchBase.cs ├── VRChat.exe └── WorldSdkPatcher.cs /AvatarSdkPatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using HarmonyLib; 3 | using UnityEditor; 4 | using UnityEngine; 5 | using VRC.SDKBase.Editor; 6 | 7 | [InitializeOnLoad] 8 | public static class AvatarSdkPatcher 9 | { 10 | public static string _steamPath; 11 | 12 | static AvatarSdkPatcher() 13 | { 14 | _steamPath = ""; 15 | if (EditorPrefs.HasKey("VRC_steamappsPath")) 16 | _steamPath = EditorPrefs.GetString("VRC_steamappsPath"); 17 | } 18 | } 19 | 20 | [HarmonyPatch(typeof(VRC_SdkBuilder))] 21 | [HarmonyPatch(nameof(VRC_SdkBuilder.GetKnownFolderPath))] 22 | class EditorPatch 23 | { 24 | static bool Prefix(ref string __result, Guid knownFolderId) 25 | { 26 | Debug.Log(knownFolderId); 27 | if (knownFolderId.ToString() == "a520a1a4-1780-4ff6-bd18-167343c5af16") 28 | { 29 | __result = EditorPrefs.GetString("VRC_steamappsPath") + 30 | "/compatdata/438100/pfx/drive_c/users/steamuser/AppData/LocalLow/"; 31 | return false; 32 | } 33 | 34 | return true; 35 | } 36 | } 37 | 38 | [HarmonyPatch(typeof(VRCSdkControlPanel))] 39 | [HarmonyPatch("OnVRCInstallPathGUI")] 40 | class ControlPanelPatch 41 | { 42 | static void Prefix() 43 | { 44 | EditorGUILayout.LabelField("Steamapps directory", EditorStyles.boldLabel); 45 | EditorGUILayout.LabelField("Steamapps directory containing VRChat"); 46 | EditorGUILayout.LabelField("Locaton: ", AvatarSdkPatcher._steamPath); 47 | EditorGUILayout.BeginHorizontal(); 48 | GUILayout.Label(""); 49 | if (GUILayout.Button("Edit")) 50 | { 51 | string initPath = ""; 52 | if (!string.IsNullOrEmpty(AvatarSdkPatcher._steamPath)) 53 | initPath = AvatarSdkPatcher._steamPath; 54 | 55 | AvatarSdkPatcher._steamPath = EditorUtility.OpenFolderPanel("Choose steamapps directory", initPath, ""); 56 | 57 | EditorPrefs.SetString("VRC_steamappsPath", AvatarSdkPatcher._steamPath); 58 | // window.OnConfigurationChanged(); 59 | } 60 | 61 | EditorGUILayout.EndHorizontal(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!WARNING] 2 | > I don't have much time to maintain this. A newer patch is available at: \ 3 | > https://befuddledlabs.github.io/LinuxVRChatSDKPatch/ \ 4 | > https://github.com/BefuddledLabs/LinuxVRChatSDKPatch 5 | 6 | # VRChat SDK Linux patch (New and improved) 7 | 8 | ## Warning: By modifying the SDK you are violating the VRChat TOS. Do it at your own risk! 9 | 10 | Now using Harmony to avoid DLL patches. 11 | 12 | ## Installation 13 | 14 | ### Unity package method 15 | Import the corresponding unitypackage. 16 | If you are using the world SDK change steamapps path in SDK settings. 17 | If you are using the avatar SDK change the client path in SDK settings to the one in Editor folder. 18 | 19 | ### Manual installation 20 | 1. Import SDK. 21 | 2. Download Harmony (https://github.com/pardeike/Harmony/releases) .NET 4.7 into `Assets/Editor` (Create if doesn't exist). 22 | 3. Copy SdkPatchBase.cs into Assets/Editor. 23 | 24 | If you are using the Avatar SDK 25 | 4. Copy AvatarSdkPatcher.cs into `Assets/Editor` 26 | 5. Select your steamapps folder location in SDK settings. 27 | 28 | If you are using the World SDK 29 | 4. Copy WorldSdkPatcher.cs into `Assets/Editor` 30 | 2. Select VRChat.exe from this repo in SDK settings 31 | 32 | ## Compatibility 33 | 34 | The last checked version is `2022.1.1` but the patches should work on newer versions 35 | -------------------------------------------------------------------------------- /SdkPatchBase.cs: -------------------------------------------------------------------------------- 1 | using HarmonyLib; 2 | using UnityEditor; 3 | 4 | namespace Editor 5 | { 6 | [InitializeOnLoad] 7 | public static class SdkPatchBase 8 | { 9 | private static Harmony _harmony; 10 | 11 | static SdkPatchBase() 12 | { 13 | if (_harmony == null) 14 | { 15 | _harmony = new Harmony("pl.barkk.vrcsdk_linux"); 16 | } 17 | 18 | 19 | _harmony.UnpatchAll(); 20 | _harmony.PatchAll(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /VRChat.exe: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | from urllib.parse import unquote, quote 5 | import re 6 | import os 7 | 8 | arg = ' '.join(sys.argv[1:]) 9 | 10 | f = open('/tmp/vrchatrun.txt', 'w') 11 | f.write(arg) 12 | f.close() 13 | 14 | url = unquote(arg) 15 | 16 | if('/tmp/' in url): 17 | url = url.replace('file:////','file://Z:/') 18 | url = url.replace('/','\\') 19 | url = url.replace('file:\\\\','file://') 20 | else: 21 | url = re.sub(r"////.*drive_c/", '//C:/', url) 22 | url = url.replace('/','\\') 23 | url = url.replace('file:\\\\','file://') 24 | 25 | #print(url.lower()) 26 | #print('xdg-open steam://run/438100//'+quote(url.lower(), '')) 27 | os.system('xdg-open steam://run/438100//'+quote(url.lower(), '')) 28 | -------------------------------------------------------------------------------- /WorldSdkPatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection.Emit; 5 | using HarmonyLib; 6 | using UnityEngine; 7 | using VRC.SDK3.Editor.Builder; 8 | 9 | [HarmonyPatch(typeof(VRCWorldAssetExporter))] 10 | [HarmonyPatch("ExportCurrentSceneResource")] 11 | class ExportCurrentSceneResourcePatch 12 | { 13 | static IEnumerable Transpiler(IEnumerable instructions) 14 | { 15 | var codes = instructions.ToList(); 16 | for (var i = 0; i < codes.Count; i++) 17 | { 18 | if (codes[i].opcode == OpCodes.Ldstr) 19 | { 20 | if (codes[i].operand.ToString().Contains(".vrcw")) 21 | { 22 | Debug.LogWarning("FOUND i = " + i); 23 | i += 3; 24 | var str2 = codes[i].operand; 25 | i++; 26 | codes.Insert(i++, new CodeInstruction(OpCodes.Ldloc_S, str2)); 27 | codes.Insert(i++,CodeInstruction.Call(typeof(String), "ToLower")); 28 | codes.Insert(i++, new CodeInstruction(OpCodes.Stloc_S, str2)); 29 | break; 30 | } 31 | } 32 | } 33 | 34 | return codes.AsEnumerable(); 35 | } 36 | } 37 | --------------------------------------------------------------------------------