ModSetup.vb 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. Public Class ModSetup
  2. ''' <summary>
  3. ''' 设置的更新号。
  4. ''' </summary>
  5. Public Const VersionSetup As Integer = 1
  6. ''' <summary>
  7. ''' 设置列表。
  8. ''' </summary>
  9. Private ReadOnly SetupDict As New Dictionary(Of String, SetupEntry) From {
  10. {"Identify", New SetupEntry("", Source:=SetupSource.Registry)},
  11. {"WindowHeight", New SetupEntry(550)},
  12. {"WindowWidth", New SetupEntry(900)},
  13. {"HintDownloadThread", New SetupEntry(False, Source:=SetupSource.Registry)},
  14. {"HintNotice", New SetupEntry(0, Source:=SetupSource.Registry)},
  15. {"HintDownload", New SetupEntry(0, Source:=SetupSource.Registry)},
  16. {"HintInstallBack", New SetupEntry(False, Source:=SetupSource.Registry)},
  17. {"HintHide", New SetupEntry(False, Source:=SetupSource.Registry)},
  18. {"HintHandInstall", New SetupEntry(False, Source:=SetupSource.Registry)},
  19. {"HintBuy", New SetupEntry(False, Source:=SetupSource.Registry)},
  20. {"HintClearRubbish", New SetupEntry(0, Source:=SetupSource.Registry)},
  21. {"HintUpdateMod", New SetupEntry(False, Source:=SetupSource.Registry)},
  22. {"HintCustomCommand", New SetupEntry(False, Source:=SetupSource.Registry)},
  23. {"HintCustomWarn", New SetupEntry(False, Source:=SetupSource.Registry)},
  24. {"HintMoreAdvancedSetup", New SetupEntry(False, Source:=SetupSource.Registry)},
  25. {"HintIndieSetup", New SetupEntry(False, Source:=SetupSource.Registry)},
  26. {"HintExportConfig", New SetupEntry(False, Source:=SetupSource.Registry)},
  27. {"SystemEula", New SetupEntry(False, Source:=SetupSource.Registry)},
  28. {"SystemCount", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
  29. {"SystemLaunchCount", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
  30. {"SystemLastVersionReg", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
  31. {"SystemHighestSavedBetaVersionReg", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
  32. {"SystemHighestBetaVersionReg", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
  33. {"SystemHighestAlphaVersionReg", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
  34. {"SystemSetupVersionReg", New SetupEntry(VersionSetup, Source:=SetupSource.Registry)},
  35. {"SystemSetupVersionIni", New SetupEntry(VersionSetup)},
  36. {"SystemHelpVersion", New SetupEntry(0, Source:=SetupSource.Registry)},
  37. {"SystemDebugMode", New SetupEntry(False, Source:=SetupSource.Registry)},
  38. {"SystemDebugAnim", New SetupEntry(9, Source:=SetupSource.Registry)},
  39. {"SystemDebugDelay", New SetupEntry(False, Source:=SetupSource.Registry)},
  40. {"SystemDebugSkipCopy", New SetupEntry(False, Source:=SetupSource.Registry)},
  41. {"SystemSystemCache", New SetupEntry("", Source:=SetupSource.Registry)},
  42. {"SystemSystemUpdate", New SetupEntry(0)},
  43. {"SystemSystemActivity", New SetupEntry(0)},
  44. {"CacheExportConfig", New SetupEntry("", Source:=SetupSource.Registry)},
  45. {"CacheSavedPageUrl", New SetupEntry("", Source:=SetupSource.Registry)},
  46. {"CacheSavedPageVersion", New SetupEntry("", Source:=SetupSource.Registry)},
  47. {"CacheMsOAuthRefresh", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  48. {"CacheMsAccess", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  49. {"CacheMsProfileJson", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  50. {"CacheMsUuid", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  51. {"CacheMsName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  52. {"CacheMsV2Migrated", New SetupEntry(False, Source:=SetupSource.Registry)},
  53. {"CacheMsV2OAuthRefresh", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  54. {"CacheMsV2Access", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  55. {"CacheMsV2ProfileJson", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  56. {"CacheMsV2Uuid", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  57. {"CacheMsV2Name", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  58. {"CacheNideAccess", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  59. {"CacheNideClient", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  60. {"CacheNideUuid", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  61. {"CacheNideName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  62. {"CacheNideUsername", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  63. {"CacheNidePass", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  64. {"CacheNideServer", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  65. {"CacheAuthAccess", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  66. {"CacheAuthClient", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  67. {"CacheAuthUuid", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  68. {"CacheAuthName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  69. {"CacheAuthUsername", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  70. {"CacheAuthPass", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  71. {"CacheAuthServerServer", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  72. {"CacheAuthServerName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  73. {"CacheAuthServerRegister", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  74. {"CacheDownloadFolder", New SetupEntry("", Source:=SetupSource.Registry)},
  75. {"CacheJavaListVersion", New SetupEntry(0, Source:=SetupSource.Registry)},
  76. {"LoginRemember", New SetupEntry(True, Source:=SetupSource.Registry, Encoded:=True)},
  77. {"LoginLegacyName", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  78. {"LoginMsJson", New SetupEntry("{}", Source:=SetupSource.Registry, Encoded:=True)}, '{UserName: OAuthToken, ...}
  79. {"LoginNideEmail", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  80. {"LoginNidePass", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  81. {"LoginAuthEmail", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  82. {"LoginAuthPass", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  83. {"LoginType", New SetupEntry(McLoginType.Legacy, Source:=SetupSource.Registry)},
  84. {"LoginPageType", New SetupEntry(0)},
  85. {"LaunchSkinID", New SetupEntry("", Source:=SetupSource.Registry)},
  86. {"LaunchSkinType", New SetupEntry(0, Source:=SetupSource.Registry)},
  87. {"LaunchSkinSlim", New SetupEntry(False, Source:=SetupSource.Registry)},
  88. {"LaunchVersionSelect", New SetupEntry("")},
  89. {"LaunchFolderSelect", New SetupEntry("")},
  90. {"LaunchFolders", New SetupEntry("", Source:=SetupSource.Registry)},
  91. {"LaunchArgumentTitle", New SetupEntry("")},
  92. {"LaunchArgumentInfo", New SetupEntry("PCL")},
  93. {"LaunchArgumentJavaSelect", New SetupEntry("", Source:=SetupSource.Registry)},
  94. {"LaunchArgumentJavaAll", New SetupEntry("[]", Source:=SetupSource.Registry)},
  95. {"LaunchArgumentIndie", New SetupEntry(0)},
  96. {"LaunchArgumentIndieV2", New SetupEntry(4)},
  97. {"LaunchArgumentVisible", New SetupEntry(5, Source:=SetupSource.Registry)},
  98. {"LaunchArgumentPriority", New SetupEntry(1, Source:=SetupSource.Registry)},
  99. {"LaunchArgumentWindowWidth", New SetupEntry(854)},
  100. {"LaunchArgumentWindowHeight", New SetupEntry(480)},
  101. {"LaunchArgumentWindowType", New SetupEntry(1)},
  102. {"LaunchArgumentRam", New SetupEntry(False, Source:=SetupSource.Registry)},
  103. {"LaunchAdvanceJvm", New SetupEntry("-XX:+UseG1GC -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Djdk.lang.Process.allowAmbiguousCommands=true -Dfml.ignoreInvalidMinecraftCertificates=True -Dfml.ignorePatchDiscrepancies=True -Dlog4j2.formatMsgNoLookups=true")},
  104. {"LaunchAdvanceGame", New SetupEntry("")},
  105. {"LaunchAdvanceRun", New SetupEntry("")},
  106. {"LaunchAdvanceRunWait", New SetupEntry(True)},
  107. {"LaunchAdvanceDisableJLW", New SetupEntry(False)},
  108. {"LaunchAdvanceGraphicCard", New SetupEntry(True, Source:=SetupSource.Registry)},
  109. {"LaunchRamType", New SetupEntry(0)},
  110. {"LaunchRamCustom", New SetupEntry(15)},
  111. {"LinkEula", New SetupEntry(False, Source:=SetupSource.Registry)},
  112. {"LinkName", New SetupEntry("", Source:=SetupSource.Registry)},
  113. {"LinkHiperCertLast", New SetupEntry("", Source:=SetupSource.Registry)},
  114. {"LinkHiperCertTime", New SetupEntry("", Source:=SetupSource.Registry)},
  115. {"LinkHiperCertWarn", New SetupEntry(True, Source:=SetupSource.Registry)},
  116. {"LinkIoiVersion", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
  117. {"ToolHelpChinese", New SetupEntry(True, Source:=SetupSource.Registry)},
  118. {"ToolDownloadThread", New SetupEntry(63, Source:=SetupSource.Registry)},
  119. {"ToolDownloadSpeed", New SetupEntry(42, Source:=SetupSource.Registry)},
  120. {"ToolDownloadSource", New SetupEntry(1, Source:=SetupSource.Registry)},
  121. {"ToolDownloadVersion", New SetupEntry(1, Source:=SetupSource.Registry)},
  122. {"ToolDownloadTranslate", New SetupEntry(0, Source:=SetupSource.Registry)},
  123. {"ToolDownloadTranslateV2", New SetupEntry(1, Source:=SetupSource.Registry)},
  124. {"ToolDownloadIgnoreQuilt", New SetupEntry(True, Source:=SetupSource.Registry)},
  125. {"ToolDownloadCert", New SetupEntry(False, Source:=SetupSource.Registry)},
  126. {"ToolDownloadMod", New SetupEntry(1, Source:=SetupSource.Registry)},
  127. {"ToolModLocalNameStyle", New SetupEntry(0, Source:=SetupSource.Registry)},
  128. {"ToolUpdateAlpha", New SetupEntry(0, Source:=SetupSource.Registry, Encoded:=True)},
  129. {"ToolUpdateRelease", New SetupEntry(False, Source:=SetupSource.Registry)},
  130. {"ToolUpdateSnapshot", New SetupEntry(False, Source:=SetupSource.Registry)},
  131. {"ToolUpdateReleaseLast", New SetupEntry("", Source:=SetupSource.Registry)},
  132. {"ToolUpdateSnapshotLast", New SetupEntry("", Source:=SetupSource.Registry)},
  133. {"UiLauncherTransparent", New SetupEntry(600)}, '避免与 PCL1 设置冲突(UiLauncherOpacity)
  134. {"UiLauncherHue", New SetupEntry(180)},
  135. {"UiLauncherSat", New SetupEntry(80)},
  136. {"UiLauncherDelta", New SetupEntry(90)},
  137. {"UiLauncherLight", New SetupEntry(20)},
  138. {"UiLauncherTheme", New SetupEntry(0)},
  139. {"UiLauncherThemeGold", New SetupEntry("", Source:=SetupSource.Registry, Encoded:=True)},
  140. {"UiLauncherThemeHide", New SetupEntry("0|1|2|3|4", Source:=SetupSource.Registry, Encoded:=True)},
  141. {"UiLauncherThemeHide2", New SetupEntry("0|1|2|3|4", Source:=SetupSource.Registry, Encoded:=True)},
  142. {"UiLauncherLogo", New SetupEntry(True)},
  143. {"UiLauncherEmail", New SetupEntry(False)},
  144. {"UiBackgroundColorful", New SetupEntry(True)},
  145. {"UiBackgroundOpacity", New SetupEntry(1000)},
  146. {"UiBackgroundBlur", New SetupEntry(0)},
  147. {"UiBackgroundSuit", New SetupEntry(0)},
  148. {"UiCustomType", New SetupEntry(0)},
  149. {"UiCustomPreset", New SetupEntry(0)},
  150. {"UiCustomNet", New SetupEntry("")},
  151. {"UiLogoType", New SetupEntry(1)},
  152. {"UiLogoText", New SetupEntry("")},
  153. {"UiLogoLeft", New SetupEntry(False)},
  154. {"UiMusicVolume", New SetupEntry(500)},
  155. {"UiMusicStop", New SetupEntry(False)},
  156. {"UiMusicStart", New SetupEntry(False)},
  157. {"UiMusicRandom", New SetupEntry(True)},
  158. {"UiMusicAuto", New SetupEntry(True)},
  159. {"UiHiddenPageDownload", New SetupEntry(False)},
  160. {"UiHiddenPageLink", New SetupEntry(False)},
  161. {"UiHiddenPageSetup", New SetupEntry(False)},
  162. {"UiHiddenPageOther", New SetupEntry(False)},
  163. {"UiHiddenFunctionSelect", New SetupEntry(False)},
  164. {"UiHiddenFunctionModUpdate", New SetupEntry(False)},
  165. {"UiHiddenFunctionHidden", New SetupEntry(False)},
  166. {"UiHiddenSetupLaunch", New SetupEntry(False)},
  167. {"UiHiddenSetupUi", New SetupEntry(False)},
  168. {"UiHiddenSetupLink", New SetupEntry(False)},
  169. {"UiHiddenSetupSystem", New SetupEntry(False)},
  170. {"UiHiddenOtherHelp", New SetupEntry(False)},
  171. {"UiHiddenOtherFeedback", New SetupEntry(False)},
  172. {"UiHiddenOtherVote", New SetupEntry(False)},
  173. {"UiHiddenOtherAbout", New SetupEntry(False)},
  174. {"UiHiddenOtherTest", New SetupEntry(False)},
  175. {"VersionAdvanceJvm", New SetupEntry("", Source:=SetupSource.Version)},
  176. {"VersionAdvanceGame", New SetupEntry("", Source:=SetupSource.Version)},
  177. {"VersionAdvanceAssets", New SetupEntry(0, Source:=SetupSource.Version)},
  178. {"VersionAdvanceAssetsV2", New SetupEntry(False, Source:=SetupSource.Version)},
  179. {"VersionAdvanceJava", New SetupEntry(False, Source:=SetupSource.Version)},
  180. {"VersionAdvanceRun", New SetupEntry("", Source:=SetupSource.Version)},
  181. {"VersionAdvanceRunWait", New SetupEntry(True, Source:=SetupSource.Version)},
  182. {"VersionAdvanceDisableJLW", New SetupEntry(False, Source:=SetupSource.Version)},
  183. {"VersionRamType", New SetupEntry(2, Source:=SetupSource.Version)},
  184. {"VersionRamCustom", New SetupEntry(15, Source:=SetupSource.Version)},
  185. {"VersionRamOptimize", New SetupEntry(0, Source:=SetupSource.Version)},
  186. {"VersionArgumentTitle", New SetupEntry("", Source:=SetupSource.Version)},
  187. {"VersionArgumentInfo", New SetupEntry("", Source:=SetupSource.Version)},
  188. {"VersionArgumentIndie", New SetupEntry(-1, Source:=SetupSource.Version)},
  189. {"VersionArgumentIndieV2", New SetupEntry(False, Source:=SetupSource.Version)},
  190. {"VersionArgumentJavaSelect", New SetupEntry("使用全局设置", Source:=SetupSource.Version)},
  191. {"VersionServerEnter", New SetupEntry("", Source:=SetupSource.Version)},
  192. {"VersionServerLogin", New SetupEntry(0, Source:=SetupSource.Version)},
  193. {"VersionServerNide", New SetupEntry("", Source:=SetupSource.Version)},
  194. {"VersionServerAuthRegister", New SetupEntry("", Source:=SetupSource.Version)},
  195. {"VersionServerAuthName", New SetupEntry("", Source:=SetupSource.Version)},
  196. {"VersionServerAuthServer", New SetupEntry("", Source:=SetupSource.Version)}
  197. }
  198. #Region "基础"
  199. Private Enum SetupSource
  200. Normal
  201. Registry
  202. Version
  203. End Enum
  204. Private Class SetupEntry
  205. Public Encoded As Boolean
  206. Public DefaultValue
  207. Public DefaultValueEncoded
  208. Public Value
  209. Public Source As SetupSource
  210. ''' <summary>
  211. ''' 加载状态:0/未读取 1/已读取未处理 2/已处理
  212. ''' 我也不知道当年写这坨的时候为啥没用 Enum……
  213. ''' </summary>
  214. Public State As Byte = 0
  215. Public Type As Type
  216. Public Sub New(Value, Optional Source = SetupSource.Normal, Optional Encoded = False)
  217. Try
  218. Me.DefaultValue = Value
  219. Me.Encoded = Encoded
  220. Me.Value = Value
  221. Me.Source = Source
  222. Me.Type = If(Value, New Object).GetType
  223. Me.DefaultValueEncoded = If(Encoded, SecretEncrypt(Value, "PCL" & UniqueAddress), Value)
  224. Catch ex As Exception
  225. Log(ex, "初始化 SetupEntry 失败", LogLevel.Feedback) '#5095 的 fallback
  226. End Try
  227. End Sub
  228. End Class
  229. ''' <summary>
  230. ''' 改变某个设置项的值。
  231. ''' </summary>
  232. Public Sub [Set](Key As String, Value As Object, Optional ForceReload As Boolean = False, Optional Version As McVersion = Nothing)
  233. [Set](Key, Value, SetupDict(Key), ForceReload, Version)
  234. End Sub
  235. Private Sub [Set](Key As String, Value As Object, E As SetupEntry, ForceReload As Boolean, Version As McVersion)
  236. Try
  237. Value = CTypeDynamic(Value, E.Type)
  238. If E.State = 2 Then
  239. '如果已应用,且值相同,则无需再次更改
  240. If E.Value = Value AndAlso Not ForceReload Then Exit Sub
  241. Else
  242. '如果未应用,则直接更改并应用
  243. If E.Source <> SetupSource.Version Then E.State = 2
  244. End If
  245. '设置新值
  246. E.Value = Value
  247. '写入值
  248. If E.Encoded Then
  249. Try
  250. If Value Is Nothing Then Value = ""
  251. Value = SecretEncrypt(Value, "PCL" & UniqueAddress)
  252. Catch ex As Exception
  253. Log(ex, "加密设置失败:" & Key, LogLevel.Developer)
  254. End Try
  255. End If
  256. Select Case E.Source
  257. Case SetupSource.Normal
  258. WriteIni("Setup", Key, Value)
  259. Case SetupSource.Registry
  260. WriteReg(Key, Value)
  261. Case SetupSource.Version
  262. If Version Is Nothing Then Throw New Exception($"更改版本设置 {Key} 时未提供目标版本")
  263. WriteIni(Version.Path & "PCL\Setup.ini", Key, Value)
  264. End Select
  265. '应用
  266. '例如 VersionServerLogin 要求在设置之后再引发事件
  267. Dim Method As Reflection.MethodInfo = GetType(ModSetup).GetMethod(Key)
  268. If Method IsNot Nothing Then Method.Invoke(Me, {Value})
  269. Catch ex As Exception
  270. Log(ex, "设置设置项时出错(" & Key & ", " & Value & ")", LogLevel.Feedback)
  271. End Try
  272. End Sub
  273. ''' <summary>
  274. ''' 应用某个设置项的值。
  275. ''' </summary>
  276. Public Function Load(Key As String, Optional ForceReload As Boolean = False, Optional Version As McVersion = Nothing)
  277. Return Load(Key, SetupDict(Key), ForceReload, Version)
  278. End Function
  279. Private Function Load(Key As String, E As SetupEntry, ForceReload As Boolean, Version As McVersion)
  280. '如果已经应用过,则什么也不干
  281. If E.State = 2 AndAlso Not ForceReload Then Return E.Value
  282. '读取,应用并设置状态
  283. Read(Key, E, Version)
  284. If E.Source <> SetupSource.Version Then E.State = 2
  285. Dim Method As Reflection.MethodInfo = GetType(ModSetup).GetMethod(Key)
  286. If Method IsNot Nothing Then Method.Invoke(Me, {E.Value})
  287. Return E.Value
  288. End Function
  289. ''' <summary>
  290. ''' 获取某个设置项的值。
  291. ''' </summary>
  292. Public Function [Get](Key As String, Optional Version As McVersion = Nothing)
  293. If Not SetupDict.ContainsKey(Key) Then Throw New KeyNotFoundException("未找到设置项:" & Key) With {.Source = Key}
  294. Return [Get](Key, SetupDict(Key), Version)
  295. End Function
  296. Private Function [Get](Key As String, E As SetupEntry, Version As McVersion)
  297. '获取强制值
  298. Dim Force As String = ForceValue(Key)
  299. If Force IsNot Nothing Then
  300. E.Value = CTypeDynamic(Force, E.Type)
  301. E.State = 1
  302. End If
  303. '如果尚未读取过,则读取
  304. If E.State = 0 Then
  305. Read(Key, E, Version)
  306. If E.Source <> SetupSource.Version Then E.State = 1
  307. End If
  308. '返回现在的值
  309. Return E.Value
  310. End Function
  311. ''' <summary>
  312. ''' 初始化某个设置项的值。
  313. ''' </summary>
  314. Public Sub Reset(Key As String, Optional ForceReload As Boolean = False, Optional Version As McVersion = Nothing)
  315. Dim E As SetupEntry = SetupDict(Key)
  316. [Set](Key, E.DefaultValue, E, ForceReload, Version)
  317. Select Case SetupDict(Key).Source
  318. Case SetupSource.Normal
  319. DeleteIniKey("Setup", Key)
  320. Case SetupSource.Registry
  321. DeleteReg(Key)
  322. Case Else 'SetupSource.Version
  323. If Version Is Nothing Then Throw New Exception($"重置版本设置 {Key} 时未提供目标版本")
  324. DeleteIniKey(Version.Path & "PCL\Setup.ini", Key)
  325. End Select
  326. End Sub
  327. ''' <summary>
  328. ''' 获取某个设置项的默认值。
  329. ''' </summary>
  330. Public Function GetDefault(Key As String) As String
  331. Return SetupDict(Key).DefaultValue
  332. End Function
  333. ''' <summary>
  334. ''' 某个设置项是否从未被设置过。
  335. ''' </summary>
  336. Public Function IsUnset(Key As String, Optional Version As McVersion = Nothing) As Boolean
  337. Select Case SetupDict(Key).Source
  338. Case SetupSource.Normal
  339. Return Not HasIniKey("Setup", Key)
  340. Case SetupSource.Registry
  341. Return Not HasReg(Key)
  342. Case Else 'SetupSource.Version
  343. If Version Is Nothing Then Throw New Exception($"判断版本设置 {Key} 是否存在时未提供目标版本")
  344. Return Not HasIniKey(Version.Path & "PCL\Setup.ini", Key)
  345. End Select
  346. End Function
  347. ''' <summary>
  348. ''' 读取设置。
  349. ''' </summary>
  350. Private Sub Read(Key As String, ByRef E As SetupEntry, Version As McVersion)
  351. Try
  352. If Not E.State = 0 Then Exit Sub
  353. Dim SourceValue As String = Nothing '先用 String 储存,避免类型转换
  354. Select Case E.Source
  355. Case SetupSource.Normal
  356. SourceValue = ReadIni("Setup", Key, E.DefaultValueEncoded)
  357. Case SetupSource.Registry
  358. SourceValue = ReadReg(Key, E.DefaultValueEncoded)
  359. Case SetupSource.Version
  360. If Version Is Nothing Then
  361. Throw New Exception("读取版本设置 " & Key & " 时未提供目标版本")
  362. Else
  363. SourceValue = ReadIni(Version.Path & "PCL\Setup.ini", Key, E.DefaultValueEncoded)
  364. End If
  365. End Select
  366. If E.Encoded Then
  367. If SourceValue.Equals(E.DefaultValueEncoded) Then
  368. SourceValue = E.DefaultValue
  369. Else
  370. Try
  371. SourceValue = SecretDecrypt(SourceValue, "PCL" & UniqueAddress)
  372. Catch ex As Exception
  373. Log(ex, "解密设置失败:" & Key, LogLevel.Developer)
  374. SourceValue = E.DefaultValue
  375. Setup.Set(Key, E.DefaultValue, True)
  376. End Try
  377. End If
  378. End If
  379. E.Value = CTypeDynamic(SourceValue, E.Type)
  380. Catch ex As Exception
  381. Log(ex, "读取设置失败:" & Key, LogLevel.Hint)
  382. E.Value = CTypeDynamic(E.DefaultValue, E.Type)
  383. End Try
  384. End Sub
  385. '对部分设置强制赋值
  386. Private Function ForceValue(Key As String) As String
  387. #If BETA Then
  388. If Key = "UiLauncherTheme" Then Return "0"
  389. #End If
  390. If Key = "UiHiddenPageLink" Then Return True
  391. If Key = "UiHiddenSetupLink" Then Return True
  392. Return Nothing
  393. End Function
  394. #End Region
  395. #Region "Launch"
  396. '切换选择
  397. Public Sub LaunchVersionSelect(Value As String)
  398. Log("[Setup] 当前选择的 Minecraft 版本:" & Value)
  399. WriteIni(PathMcFolder & "PCL.ini", "Version", If(IsNothing(McVersionCurrent), "", McVersionCurrent.Name))
  400. End Sub
  401. Public Sub LaunchFolderSelect(Value As String)
  402. Log("[Setup] 当前选择的 Minecraft 文件夹:" & Value.ToString.Replace("$", Path))
  403. PathMcFolder = Value.ToString.Replace("$", Path)
  404. End Sub
  405. '游戏内存
  406. Public Sub LaunchRamType(Type As Integer)
  407. If FrmSetupLaunch Is Nothing Then Exit Sub
  408. FrmSetupLaunch.RamType(Type)
  409. End Sub
  410. '离线皮肤
  411. Public Sub LaunchSkinType(Value As Integer)
  412. RunInUi(Sub()
  413. If Not IsNothing(FrmSetupLaunch) Then
  414. Select Case Value
  415. Case 0, 1, 2 '默认
  416. FrmSetupLaunch.PanSkinID.Visibility = Visibility.Collapsed
  417. FrmSetupLaunch.PanSkinChange.Visibility = Visibility.Collapsed
  418. Case 3 '正版
  419. FrmSetupLaunch.PanSkinID.Visibility = Visibility.Visible
  420. FrmSetupLaunch.PanSkinChange.Visibility = Visibility.Collapsed
  421. Case 4 '自定义
  422. FrmSetupLaunch.PanSkinID.Visibility = Visibility.Collapsed
  423. FrmSetupLaunch.PanSkinChange.Visibility = Visibility.Visible
  424. End Select
  425. FrmSetupLaunch.CardSkin.TriggerForceResize()
  426. End If
  427. PageLaunchLeft.SkinLegacy.Start()
  428. End Sub)
  429. End Sub
  430. Public Sub LaunchSkinID(Value As String)
  431. PageLaunchLeft.SkinLegacy.Start()
  432. End Sub
  433. #End Region
  434. #Region "Tool"
  435. Public Sub ToolDownloadThread(Value As Integer)
  436. NetTaskThreadLimit = Value + 1
  437. End Sub
  438. Public Sub ToolDownloadCert(Value As Boolean)
  439. ServicePointManager.ServerCertificateValidationCallback =
  440. Function(Sender, Certificate, Chain, Failure)
  441. Dim Request As HttpWebRequest = TryCast(Sender, HttpWebRequest)
  442. If Failure = Net.Security.SslPolicyErrors.None Then Return True '已通过验证
  443. '基于 #3018 和 #5879,只在访问正版登录 API 时跳过证书验证
  444. Log($"[System] 未通过 SSL 证书验证({Failure}),提供的证书为 {Certificate?.Subject},URL:{Request?.Address}", LogLevel.Debug)
  445. If Request Is Nothing Then
  446. Return Not Value
  447. ElseIf Request.Address.Host.Contains("xboxlive") OrElse Request.Address.Host.Contains("minecraftservices") Then
  448. Return Not Value '根据设置决定是否忽略错误
  449. Else
  450. Return False
  451. End If
  452. End Function
  453. End Sub
  454. Public Sub ToolDownloadSpeed(Value As Integer)
  455. If Value <= 14 Then
  456. NetTaskSpeedLimitHigh = (Value + 1) * 0.1 * 1024 * 1024L
  457. ElseIf Value <= 31 Then
  458. NetTaskSpeedLimitHigh = (Value - 11) * 0.5 * 1024 * 1024L
  459. ElseIf Value <= 41 Then
  460. NetTaskSpeedLimitHigh = (Value - 21) * 1024 * 1024L
  461. Else
  462. NetTaskSpeedLimitHigh = -1
  463. End If
  464. End Sub
  465. #End Region
  466. #Region "UI"
  467. '启动器
  468. Public Sub UiLauncherTransparent(Value As Integer)
  469. FrmMain.Opacity = Value / 1000 + 0.4
  470. End Sub
  471. #If Not BETA Then
  472. Public Sub UiLauncherTheme(Value As Integer)
  473. ThemeRefresh(Value)
  474. End Sub
  475. #End If
  476. Public Sub UiBackgroundColorful(Value As Boolean)
  477. ThemeRefresh()
  478. End Sub
  479. '背景图片
  480. Public Sub UiBackgroundOpacity(Value As Integer)
  481. FrmMain.ImgBack.Opacity = Value / 1000
  482. End Sub
  483. Public Sub UiBackgroundBlur(Value As Integer)
  484. If Value = 0 Then
  485. FrmMain.ImgBack.Effect = Nothing
  486. Else
  487. FrmMain.ImgBack.Effect = New Effects.BlurEffect With {.Radius = Value + 1}
  488. End If
  489. FrmMain.ImgBack.Margin = New Thickness(-(Value + 1) / 1.8)
  490. End Sub
  491. Public Sub UiBackgroundSuit(Value As Integer)
  492. If IsNothing(FrmMain.ImgBack.Background) Then Exit Sub
  493. Dim Width As Double = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  494. Dim Height As Double = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  495. If Value = 0 Then
  496. '智能:当图片较小时平铺,较大时适应
  497. If Width < FrmMain.PanMain.ActualWidth / 2 AndAlso Height < FrmMain.PanMain.ActualHeight / 2 Then
  498. Value = 4 '平铺
  499. Else
  500. Value = 2 '适应
  501. End If
  502. End If
  503. CType(FrmMain.ImgBack.Background, ImageBrush).TileMode = TileMode.None
  504. CType(FrmMain.ImgBack.Background, ImageBrush).Viewport = New Rect(0, 0, 1, 1)
  505. CType(FrmMain.ImgBack.Background, ImageBrush).ViewportUnits = BrushMappingMode.RelativeToBoundingBox
  506. Select Case Value
  507. Case 1 '居中
  508. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Center
  509. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Center
  510. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  511. FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  512. FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  513. Case 2 '适应
  514. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Stretch
  515. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Stretch
  516. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.UniformToFill
  517. FrmMain.ImgBack.Width = Double.NaN
  518. FrmMain.ImgBack.Height = Double.NaN
  519. Case 3 '拉伸
  520. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Stretch
  521. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Stretch
  522. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.Fill
  523. FrmMain.ImgBack.Width = Double.NaN
  524. FrmMain.ImgBack.Height = Double.NaN
  525. Case 4 '平铺
  526. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Stretch
  527. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Stretch
  528. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  529. CType(FrmMain.ImgBack.Background, ImageBrush).TileMode = TileMode.Tile
  530. CType(FrmMain.ImgBack.Background, ImageBrush).Viewport = New Rect(0, 0, CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width, CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height)
  531. CType(FrmMain.ImgBack.Background, ImageBrush).ViewportUnits = BrushMappingMode.Absolute
  532. FrmMain.ImgBack.Width = Double.NaN
  533. FrmMain.ImgBack.Height = Double.NaN
  534. Case 5 '左上
  535. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Left
  536. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Top
  537. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  538. FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  539. FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  540. Case 6 '右上
  541. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Right
  542. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Top
  543. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  544. FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  545. FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  546. Case 7 '左下
  547. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Left
  548. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Bottom
  549. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  550. FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  551. FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  552. Case 8 '右下
  553. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Right
  554. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Bottom
  555. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  556. FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  557. FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  558. End Select
  559. End Sub
  560. '主页
  561. Public Sub UiCustomType(Value As Integer)
  562. If FrmSetupUI Is Nothing Then Exit Sub
  563. Select Case Value
  564. Case 0 '无
  565. FrmSetupUI.PanCustomPreset.Visibility = Visibility.Collapsed
  566. FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
  567. FrmSetupUI.PanCustomNet.Visibility = Visibility.Collapsed
  568. FrmSetupUI.HintCustom.Visibility = Visibility.Collapsed
  569. FrmSetupUI.HintCustomWarn.Visibility = Visibility.Collapsed
  570. Case 1 '本地
  571. FrmSetupUI.PanCustomPreset.Visibility = Visibility.Collapsed
  572. FrmSetupUI.PanCustomLocal.Visibility = Visibility.Visible
  573. FrmSetupUI.PanCustomNet.Visibility = Visibility.Collapsed
  574. FrmSetupUI.HintCustom.Visibility = Visibility.Visible
  575. FrmSetupUI.HintCustomWarn.Visibility = If(Setup.Get("HintCustomWarn"), Visibility.Collapsed, Visibility.Visible)
  576. FrmSetupUI.HintCustom.Text = $"从 PCL 文件夹下的 Custom.xaml 读取主页内容。{vbCrLf}你可以手动编辑该文件,向主页添加文本、图片、常用网站、快捷启动等功能。"
  577. FrmSetupUI.HintCustom.EventType = ""
  578. FrmSetupUI.HintCustom.EventData = ""
  579. Case 2 '联网
  580. FrmSetupUI.PanCustomPreset.Visibility = Visibility.Collapsed
  581. FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
  582. FrmSetupUI.PanCustomNet.Visibility = Visibility.Visible
  583. FrmSetupUI.HintCustom.Visibility = Visibility.Visible
  584. FrmSetupUI.HintCustomWarn.Visibility = If(Setup.Get("HintCustomWarn"), Visibility.Collapsed, Visibility.Visible)
  585. FrmSetupUI.HintCustom.Text = $"从指定网址联网获取主页内容。服主也可以用于动态更新服务器公告。{vbCrLf}如果你制作了稳定运行的联网主页,可以点击这条提示投稿,若合格即可加入预设!"
  586. FrmSetupUI.HintCustom.EventType = "打开网页"
  587. FrmSetupUI.HintCustom.EventData = "https://github.com/Hex-Dragon/PCL2/discussions/2528"
  588. Case 3 '预设
  589. FrmSetupUI.PanCustomPreset.Visibility = Visibility.Visible
  590. FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
  591. FrmSetupUI.PanCustomNet.Visibility = Visibility.Collapsed
  592. FrmSetupUI.HintCustom.Visibility = Visibility.Collapsed
  593. FrmSetupUI.HintCustomWarn.Visibility = Visibility.Collapsed
  594. End Select
  595. FrmSetupUI.CardCustom.TriggerForceResize()
  596. End Sub
  597. '顶部栏
  598. Public Sub UiLogoType(Value As Integer)
  599. Select Case Value
  600. Case 0 '无
  601. FrmMain.ShapeTitleLogo.Visibility = Visibility.Collapsed
  602. FrmMain.LabTitleLogo.Visibility = Visibility.Collapsed
  603. FrmMain.ImageTitleLogo.Visibility = Visibility.Collapsed
  604. If Not IsNothing(FrmSetupUI) Then
  605. FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Visible
  606. FrmSetupUI.PanLogoText.Visibility = Visibility.Collapsed
  607. FrmSetupUI.PanLogoChange.Visibility = Visibility.Collapsed
  608. End If
  609. Case 1 '默认
  610. FrmMain.ShapeTitleLogo.Visibility = Visibility.Visible
  611. FrmMain.LabTitleLogo.Visibility = Visibility.Collapsed
  612. FrmMain.ImageTitleLogo.Visibility = Visibility.Collapsed
  613. If Not IsNothing(FrmSetupUI) Then
  614. FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Collapsed
  615. FrmSetupUI.PanLogoText.Visibility = Visibility.Collapsed
  616. FrmSetupUI.PanLogoChange.Visibility = Visibility.Collapsed
  617. End If
  618. Case 2 '文本
  619. FrmMain.ShapeTitleLogo.Visibility = Visibility.Collapsed
  620. FrmMain.LabTitleLogo.Visibility = Visibility.Visible
  621. FrmMain.ImageTitleLogo.Visibility = Visibility.Collapsed
  622. If Not IsNothing(FrmSetupUI) Then
  623. FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Collapsed
  624. FrmSetupUI.PanLogoText.Visibility = Visibility.Visible
  625. FrmSetupUI.PanLogoChange.Visibility = Visibility.Collapsed
  626. End If
  627. Setup.Load("UiLogoText", True)
  628. Case 3 '图片
  629. FrmMain.ShapeTitleLogo.Visibility = Visibility.Collapsed
  630. FrmMain.LabTitleLogo.Visibility = Visibility.Collapsed
  631. FrmMain.ImageTitleLogo.Visibility = Visibility.Visible
  632. If Not IsNothing(FrmSetupUI) Then
  633. FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Collapsed
  634. FrmSetupUI.PanLogoText.Visibility = Visibility.Collapsed
  635. FrmSetupUI.PanLogoChange.Visibility = Visibility.Visible
  636. End If
  637. Try
  638. FrmMain.ImageTitleLogo.Source = Path & "PCL\Logo.png"
  639. Catch ex As Exception
  640. FrmMain.ImageTitleLogo.Source = Nothing
  641. Log(ex, "显示标题栏图片失败", LogLevel.Msgbox)
  642. End Try
  643. End Select
  644. Setup.Load("UiLogoLeft", True)
  645. If Not IsNothing(FrmSetupUI) Then FrmSetupUI.CardLogo.TriggerForceResize()
  646. End Sub
  647. Public Sub UiLogoText(Value As String)
  648. FrmMain.LabTitleLogo.Text = Value
  649. End Sub
  650. Public Sub UiLogoLeft(Value As Boolean)
  651. FrmMain.PanTitleMain.ColumnDefinitions(0).Width = New GridLength(If(Value AndAlso (Setup.Get("UiLogoType") = 0), 0, 1), GridUnitType.Star)
  652. End Sub
  653. '功能隐藏
  654. Public Sub UiHiddenPageLink(Value As Boolean)
  655. PageSetupUI.HiddenRefresh()
  656. End Sub
  657. Public Sub UiHiddenPageDownload(Value As Boolean)
  658. PageSetupUI.HiddenRefresh()
  659. End Sub
  660. Public Sub UiHiddenPageSetup(Value As Boolean)
  661. PageSetupUI.HiddenRefresh()
  662. End Sub
  663. Public Sub UiHiddenPageOther(Value As Boolean)
  664. PageSetupUI.HiddenRefresh()
  665. End Sub
  666. Public Sub UiHiddenFunctionSelect(Value As Boolean)
  667. PageSetupUI.HiddenRefresh()
  668. End Sub
  669. Public Sub UiHiddenFunctionModUpdate(Value As Boolean)
  670. PageSetupUI.HiddenRefresh()
  671. End Sub
  672. Public Sub UiHiddenFunctionHidden(Value As Boolean)
  673. PageSetupUI.HiddenRefresh()
  674. End Sub
  675. Public Sub UiHiddenSetupLaunch(Value As Boolean)
  676. PageSetupUI.HiddenRefresh()
  677. End Sub
  678. Public Sub UiHiddenSetupUi(Value As Boolean)
  679. PageSetupUI.HiddenRefresh()
  680. End Sub
  681. Public Sub UiHiddenSetupLink(Value As Boolean)
  682. PageSetupUI.HiddenRefresh()
  683. End Sub
  684. Public Sub UiHiddenSetupSystem(Value As Boolean)
  685. PageSetupUI.HiddenRefresh()
  686. End Sub
  687. Public Sub UiHiddenOtherHelp(Value As Boolean)
  688. PageSetupUI.HiddenRefresh()
  689. End Sub
  690. Public Sub UiHiddenOtherFeedback(Value As Boolean)
  691. PageSetupUI.HiddenRefresh()
  692. End Sub
  693. Public Sub UiHiddenOtherVote(Value As Boolean)
  694. PageSetupUI.HiddenRefresh()
  695. End Sub
  696. Public Sub UiHiddenOtherAbout(Value As Boolean)
  697. PageSetupUI.HiddenRefresh()
  698. End Sub
  699. Public Sub UiHiddenOtherTest(Value As Boolean)
  700. PageSetupUI.HiddenRefresh()
  701. End Sub
  702. #End Region
  703. #Region "System"
  704. '调试选项
  705. Public Sub SystemDebugMode(Value As Boolean)
  706. ModeDebug = Value
  707. End Sub
  708. Public Sub SystemDebugAnim(Value As Integer)
  709. AniSpeed = If(Value >= 30, 200, MathClamp(Value * 0.1 + 0.1, 0.1, 3))
  710. End Sub
  711. #End Region
  712. #Region "Version"
  713. '游戏内存
  714. Public Sub VersionRamType(Type As Integer)
  715. If FrmVersionSetup Is Nothing Then Exit Sub
  716. FrmVersionSetup.RamType(Type)
  717. End Sub
  718. '服务器
  719. Public Sub VersionServerLogin(Type As Integer)
  720. If FrmVersionSetup Is Nothing Then Exit Sub
  721. '为第三方登录清空缓存以更新描述
  722. WriteIni(PathMcFolder & "PCL.ini", "VersionCache", "")
  723. If PageVersionLeft.Version Is Nothing Then Exit Sub
  724. PageVersionLeft.Version = New McVersion(PageVersionLeft.Version.Name).Load()
  725. LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
  726. End Sub
  727. #End Region
  728. End Class