@@ -12,6 +12,7 @@ import java.io.FileReader
1212import java.io.InvalidObjectException
1313import java.nio.ByteBuffer
1414import java.nio.ByteOrder
15+ import java.nio.file.Path
1516import kotlin.io.path.Path
1617import kotlin.io.path.exists
1718
@@ -142,13 +143,78 @@ class RegEditLinux : AbstractRegEdit() {
142143 }
143144
144145 companion object {
145- const val USER_REG_SUBPATH = " steamapps/compatdata/438100/pfx/user.reg"
146- val USER_REG_PATH =
147- System .getenv(" HOME" )?.let {
148- Path (it, " .steam" , " root" , USER_REG_SUBPATH ).let { if (it.exists()) it else null }
149- ? : Path (it, " .steam" , " debian-installation" , USER_REG_SUBPATH ).let { if (it.exists()) it else null }
150- ? : Path (it, " .var" , " app" , " com.valvesoftware.Steam" , " data" , " Steam" , USER_REG_SUBPATH ).let { if (it.exists()) it else null }
146+ private fun findAppLibraryLocation (steamPath : Path , appId : Int ): Path ? {
147+ val keyValueRegex = Regex (""" "(\w+)"[ \t]*(?:"(.+)")?""" )
148+ try {
149+ BufferedReader (FileReader (steamPath.resolve(" config/libraryfolders.vdf" ).toFile())).use { reader ->
150+ var depth = 0
151+ var currentLibraryPath: Path ? = null
152+
153+ while (reader.ready()) {
154+ val line = reader.readLine().trim()
155+ if (line == " {" ) {
156+ depth + = 1
157+ continue
158+ }
159+ if (line == " }" ) {
160+ depth - = 1
161+ continue
162+ }
163+
164+ keyValueRegex.matchEntire(line)?.let {
165+ val key = it.groupValues[1 ]
166+ val value = it.groupValues[2 ]
167+
168+ when (depth) {
169+ 0 -> {
170+ require(key == " libraryfolders" ) { " root key must be libraryfolders" }
171+ }
172+
173+ 1 -> {
174+ // start of a library node
175+ }
176+
177+ 2 -> {
178+ // in a library node
179+ if (key == " path" ) {
180+ currentLibraryPath = Path (value)
181+ } else if (key == " apps" ) {
182+ // start of apps node
183+ require(currentLibraryPath != null ) { " path must come before apps in node" }
184+ }
185+ }
186+
187+ 3 -> {
188+ // in apps node
189+ val curAppId = try {
190+ key.toInt()
191+ } catch (_: NumberFormatException ) {
192+ null
193+ }
194+ if (curAppId != null && curAppId == appId) {
195+ assert (currentLibraryPath != null )
196+ return currentLibraryPath
197+ }
198+ }
199+ }
200+ }
201+ }
202+ LogManager .warning(" [VRChatRegEdit] Couldn't find library folder for appid $appId " )
203+ }
204+ } catch (e: Exception ) {
205+ LogManager .severe(" [VRChatRegEdit] Error parsing Steam libraryfolders" , e)
151206 }
207+ return null
208+ }
209+
210+ const val USER_REG_SUBPATH = " steamapps/compatdata/438100/pfx/user.reg"
211+ val STEAM_PATH = System .getenv(" HOME" )?.let { home ->
212+ Path (home, " .steam" , " root" ).takeIf { it.exists() }
213+ ? : Path (home, " .steam" , " debian-installation" ).takeIf { it.exists() }
214+ ? : Path (home, " .var" , " app" , " com.valvesoftware.Steam" , " data" , " Steam" ).takeIf { it.exists() }
215+ }
216+ val USER_REG_PATH : Path ? = if (STEAM_PATH != null ) findAppLibraryLocation(STEAM_PATH , 438100 )?.resolve(USER_REG_SUBPATH ) else null
217+
152218 val KEY_VALUE_PATTERN = Regex (""" "(.+)"=(.+)""" )
153219
154220 val HEX_FORMAT = HexFormat {
0 commit comments