ModSetup.vb 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  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. {"VersionCanModUpdate", New SetupEntry(True, Source:=SetupSource.Version)}
  198. }
  199. #Region "基础"
  200. Private Enum SetupSource
  201. Normal
  202. Registry
  203. Version
  204. End Enum
  205. Private Class SetupEntry
  206. Public Encoded As Boolean
  207. Public DefaultValue
  208. Public DefaultValueEncoded
  209. Public Value
  210. Public Source As SetupSource
  211. ''' <summary>
  212. ''' 加载状态:0/未读取 1/已读取未处理 2/已处理
  213. ''' 我也不知道当年写这坨的时候为啥没用 Enum……
  214. ''' </summary>
  215. Public State As Byte = 0
  216. Public Type As Type
  217. Public Sub New(Value, Optional Source = SetupSource.Normal, Optional Encoded = False)
  218. Try
  219. Me.DefaultValue = Value
  220. Me.Encoded = Encoded
  221. Me.Value = Value
  222. Me.Source = Source
  223. Me.Type = If(Value, New Object).GetType
  224. Me.DefaultValueEncoded = If(Encoded, SecretEncrypt(Value, "PCL" & UniqueAddress), Value)
  225. Catch ex As Exception
  226. Log(ex, "初始化 SetupEntry 失败", LogLevel.Feedback) '#5095 的 fallback
  227. End Try
  228. End Sub
  229. End Class
  230. ''' <summary>
  231. ''' 改变某个设置项的值。
  232. ''' </summary>
  233. Public Sub [Set](Key As String, Value As Object, Optional ForceReload As Boolean = False, Optional Version As McVersion = Nothing)
  234. [Set](Key, Value, SetupDict(Key), ForceReload, Version)
  235. End Sub
  236. Private Sub [Set](Key As String, Value As Object, E As SetupEntry, ForceReload As Boolean, Version As McVersion)
  237. Try
  238. Value = CTypeDynamic(Value, E.Type)
  239. If E.State = 2 Then
  240. '如果已应用,且值相同,则无需再次更改
  241. If E.Value = Value AndAlso Not ForceReload Then Return
  242. Else
  243. '如果未应用,则直接更改并应用
  244. If E.Source <> SetupSource.Version Then E.State = 2
  245. End If
  246. '设置新值
  247. E.Value = Value
  248. '写入值
  249. If E.Encoded Then
  250. Try
  251. If Value Is Nothing Then Value = ""
  252. Value = SecretEncrypt(Value, "PCL" & UniqueAddress)
  253. Catch ex As Exception
  254. Log(ex, "加密设置失败:" & Key, LogLevel.Developer)
  255. End Try
  256. End If
  257. Select Case E.Source
  258. Case SetupSource.Normal
  259. WriteIni("Setup", Key, Value)
  260. Case SetupSource.Registry
  261. WriteReg(Key, Value)
  262. Case SetupSource.Version
  263. If Version Is Nothing Then Throw New Exception($"更改版本设置 {Key} 时未提供目标版本")
  264. WriteIni(Version.Path & "PCL\Setup.ini", Key, Value)
  265. End Select
  266. '应用
  267. '例如 VersionServerLogin 要求在设置之后再引发事件
  268. Dim Method As Reflection.MethodInfo = GetType(ModSetup).GetMethod(Key)
  269. If Method IsNot Nothing Then Method.Invoke(Me, {Value})
  270. Catch ex As Exception
  271. Log(ex, "设置设置项时出错(" & Key & ", " & Value & ")", LogLevel.Feedback)
  272. End Try
  273. End Sub
  274. ''' <summary>
  275. ''' 应用某个设置项的值。
  276. ''' </summary>
  277. Public Function Load(Key As String, Optional ForceReload As Boolean = False, Optional Version As McVersion = Nothing)
  278. Return Load(Key, SetupDict(Key), ForceReload, Version)
  279. End Function
  280. Private Function Load(Key As String, E As SetupEntry, ForceReload As Boolean, Version As McVersion)
  281. '如果已经应用过,则什么也不干
  282. If E.State = 2 AndAlso Not ForceReload Then Return E.Value
  283. '读取,应用并设置状态
  284. Read(Key, E, Version)
  285. If E.Source <> SetupSource.Version Then E.State = 2
  286. Dim Method As Reflection.MethodInfo = GetType(ModSetup).GetMethod(Key)
  287. If Method IsNot Nothing Then Method.Invoke(Me, {E.Value})
  288. Return E.Value
  289. End Function
  290. ''' <summary>
  291. ''' 获取某个设置项的值。
  292. ''' </summary>
  293. Public Function [Get](Key As String, Optional Version As McVersion = Nothing)
  294. If Not SetupDict.ContainsKey(Key) Then Throw New KeyNotFoundException("未找到设置项:" & Key) With {.Source = Key}
  295. Return [Get](Key, SetupDict(Key), Version)
  296. End Function
  297. Private Function [Get](Key As String, E As SetupEntry, Version As McVersion)
  298. '获取强制值
  299. Dim Force As String = ForceValue(Key)
  300. If Force IsNot Nothing Then
  301. E.Value = CTypeDynamic(Force, E.Type)
  302. E.State = 1
  303. End If
  304. '如果尚未读取过,则读取
  305. If E.State = 0 Then
  306. Read(Key, E, Version)
  307. If E.Source <> SetupSource.Version Then E.State = 1
  308. End If
  309. '返回现在的值
  310. Return E.Value
  311. End Function
  312. ''' <summary>
  313. ''' 初始化某个设置项的值。
  314. ''' </summary>
  315. Public Sub Reset(Key As String, Optional ForceReload As Boolean = False, Optional Version As McVersion = Nothing)
  316. Dim E As SetupEntry = SetupDict(Key)
  317. [Set](Key, E.DefaultValue, E, ForceReload, Version)
  318. Select Case SetupDict(Key).Source
  319. Case SetupSource.Normal
  320. DeleteIniKey("Setup", Key)
  321. Case SetupSource.Registry
  322. DeleteReg(Key)
  323. Case Else 'SetupSource.Version
  324. If Version Is Nothing Then Throw New Exception($"重置版本设置 {Key} 时未提供目标版本")
  325. DeleteIniKey(Version.Path & "PCL\Setup.ini", Key)
  326. End Select
  327. End Sub
  328. ''' <summary>
  329. ''' 获取某个设置项的默认值。
  330. ''' </summary>
  331. Public Function GetDefault(Key As String) As String
  332. Return SetupDict(Key).DefaultValue
  333. End Function
  334. ''' <summary>
  335. ''' 某个设置项是否从未被设置过。
  336. ''' </summary>
  337. Public Function IsUnset(Key As String, Optional Version As McVersion = Nothing) As Boolean
  338. Select Case SetupDict(Key).Source
  339. Case SetupSource.Normal
  340. Return Not HasIniKey("Setup", Key)
  341. Case SetupSource.Registry
  342. Return Not HasReg(Key)
  343. Case Else 'SetupSource.Version
  344. If Version Is Nothing Then Throw New Exception($"判断版本设置 {Key} 是否存在时未提供目标版本")
  345. Return Not HasIniKey(Version.Path & "PCL\Setup.ini", Key)
  346. End Select
  347. End Function
  348. ''' <summary>
  349. ''' 读取设置。
  350. ''' </summary>
  351. Private Sub Read(Key As String, ByRef E As SetupEntry, Version As McVersion)
  352. Try
  353. If Not E.State = 0 Then Return
  354. Dim SourceValue As String = Nothing '先用 String 储存,避免类型转换
  355. Select Case E.Source
  356. Case SetupSource.Normal
  357. SourceValue = ReadIni("Setup", Key, E.DefaultValueEncoded)
  358. Case SetupSource.Registry
  359. SourceValue = ReadReg(Key, E.DefaultValueEncoded)
  360. Case SetupSource.Version
  361. If Version Is Nothing Then
  362. Throw New Exception("读取版本设置 " & Key & " 时未提供目标版本")
  363. Else
  364. SourceValue = ReadIni(Version.Path & "PCL\Setup.ini", Key, E.DefaultValueEncoded)
  365. End If
  366. End Select
  367. If E.Encoded Then
  368. If SourceValue.Equals(E.DefaultValueEncoded) Then
  369. SourceValue = E.DefaultValue
  370. Else
  371. Try
  372. SourceValue = SecretDecrypt(SourceValue, "PCL" & UniqueAddress)
  373. Catch ex As Exception
  374. Log(ex, "解密设置失败:" & Key, LogLevel.Developer)
  375. SourceValue = E.DefaultValue
  376. Setup.Set(Key, E.DefaultValue, True)
  377. End Try
  378. End If
  379. End If
  380. E.Value = CTypeDynamic(SourceValue, E.Type)
  381. Catch ex As Exception
  382. Log(ex, "读取设置失败:" & Key, LogLevel.Hint)
  383. E.Value = CTypeDynamic(E.DefaultValue, E.Type)
  384. End Try
  385. End Sub
  386. '对部分设置强制赋值
  387. Private Function ForceValue(Key As String) As String
  388. #If BETA Then
  389. If Key = "UiLauncherTheme" Then Return "0"
  390. #End If
  391. If Key = "UiHiddenPageLink" Then Return True
  392. If Key = "UiHiddenSetupLink" Then Return True
  393. Return Nothing
  394. End Function
  395. #End Region
  396. #Region "Launch"
  397. '切换选择
  398. Public Sub LaunchVersionSelect(Value As String)
  399. Log("[Setup] 当前选择的 Minecraft 版本:" & Value)
  400. WriteIni(PathMcFolder & "PCL.ini", "Version", If(IsNothing(McVersionCurrent), "", McVersionCurrent.Name))
  401. End Sub
  402. Public Sub LaunchFolderSelect(Value As String)
  403. Log("[Setup] 当前选择的 Minecraft 文件夹:" & Value.ToString.Replace("$", Path))
  404. PathMcFolder = Value.ToString.Replace("$", Path)
  405. End Sub
  406. '游戏内存
  407. Public Sub LaunchRamType(Type As Integer)
  408. If FrmSetupLaunch Is Nothing Then Return
  409. FrmSetupLaunch.RamType(Type)
  410. End Sub
  411. '离线皮肤
  412. Public Sub LaunchSkinType(Value As Integer)
  413. RunInUi(Sub()
  414. If Not IsNothing(FrmSetupLaunch) Then
  415. Select Case Value
  416. Case 0, 1, 2 '默认
  417. FrmSetupLaunch.PanSkinID.Visibility = Visibility.Collapsed
  418. FrmSetupLaunch.PanSkinChange.Visibility = Visibility.Collapsed
  419. Case 3 '正版
  420. FrmSetupLaunch.PanSkinID.Visibility = Visibility.Visible
  421. FrmSetupLaunch.PanSkinChange.Visibility = Visibility.Collapsed
  422. Case 4 '自定义
  423. FrmSetupLaunch.PanSkinID.Visibility = Visibility.Collapsed
  424. FrmSetupLaunch.PanSkinChange.Visibility = Visibility.Visible
  425. End Select
  426. FrmSetupLaunch.CardSkin.TriggerForceResize()
  427. End If
  428. PageLaunchLeft.SkinLegacy.Start()
  429. End Sub)
  430. End Sub
  431. Public Sub LaunchSkinID(Value As String)
  432. PageLaunchLeft.SkinLegacy.Start()
  433. End Sub
  434. #End Region
  435. #Region "Tool"
  436. Public Sub ToolDownloadThread(Value As Integer)
  437. NetTaskThreadLimit = Value + 1
  438. End Sub
  439. Public Sub ToolDownloadCert(Value As Boolean)
  440. ServicePointManager.ServerCertificateValidationCallback =
  441. Function(Sender, Certificate, Chain, Failure)
  442. Dim Request As HttpWebRequest = TryCast(Sender, HttpWebRequest)
  443. If Failure = Net.Security.SslPolicyErrors.None Then Return True '已通过验证
  444. '基于 #3018 和 #5879,只在访问正版登录 API 时跳过证书验证
  445. Log($"[System] 未通过 SSL 证书验证({Failure}),提供的证书为 {Certificate?.Subject},URL:{Request?.Address}", LogLevel.Debug)
  446. If Request Is Nothing Then
  447. Return Not Value
  448. ElseIf Request.Address.Host.Contains("xboxlive") OrElse Request.Address.Host.Contains("minecraftservices") Then
  449. Return Not Value '根据设置决定是否忽略错误
  450. Else
  451. Return False
  452. End If
  453. End Function
  454. End Sub
  455. Public Sub ToolDownloadSpeed(Value As Integer)
  456. If Value <= 14 Then
  457. NetTaskSpeedLimitHigh = (Value + 1) * 0.1 * 1024 * 1024L
  458. ElseIf Value <= 31 Then
  459. NetTaskSpeedLimitHigh = (Value - 11) * 0.5 * 1024 * 1024L
  460. ElseIf Value <= 41 Then
  461. NetTaskSpeedLimitHigh = (Value - 21) * 1024 * 1024L
  462. Else
  463. NetTaskSpeedLimitHigh = -1
  464. End If
  465. End Sub
  466. #End Region
  467. #Region "UI"
  468. '启动器
  469. Public Sub UiLauncherTransparent(Value As Integer)
  470. FrmMain.Opacity = Value / 1000 + 0.4
  471. End Sub
  472. Public Sub UiLauncherTheme(Value As Integer)
  473. ThemeRefresh(Value)
  474. End Sub
  475. Public Sub UiBackgroundColorful(Value As Boolean)
  476. ThemeRefresh()
  477. End Sub
  478. '背景图片
  479. Public Sub UiBackgroundOpacity(Value As Integer)
  480. FrmMain.ImgBack.Opacity = Value / 1000
  481. End Sub
  482. Public Sub UiBackgroundBlur(Value As Integer)
  483. If Value = 0 Then
  484. FrmMain.ImgBack.Effect = Nothing
  485. Else
  486. FrmMain.ImgBack.Effect = New Effects.BlurEffect With {.Radius = Value + 1}
  487. End If
  488. FrmMain.ImgBack.Margin = New Thickness(-(Value + 1) / 1.8)
  489. End Sub
  490. Public Sub UiBackgroundSuit(Value As Integer)
  491. If IsNothing(FrmMain.ImgBack.Background) Then Return
  492. Dim Width As Double = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  493. Dim Height As Double = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  494. If Value = 0 Then
  495. '智能:当图片较小时平铺,较大时适应
  496. If Width < FrmMain.PanMain.ActualWidth / 2 AndAlso Height < FrmMain.PanMain.ActualHeight / 2 Then
  497. Value = 4 '平铺
  498. Else
  499. Value = 2 '适应
  500. End If
  501. End If
  502. CType(FrmMain.ImgBack.Background, ImageBrush).TileMode = TileMode.None
  503. CType(FrmMain.ImgBack.Background, ImageBrush).Viewport = New Rect(0, 0, 1, 1)
  504. CType(FrmMain.ImgBack.Background, ImageBrush).ViewportUnits = BrushMappingMode.RelativeToBoundingBox
  505. Select Case Value
  506. Case 1 '居中
  507. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Center
  508. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Center
  509. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  510. FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  511. FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  512. Case 2 '适应
  513. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Stretch
  514. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Stretch
  515. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.UniformToFill
  516. FrmMain.ImgBack.Width = Double.NaN
  517. FrmMain.ImgBack.Height = Double.NaN
  518. Case 3 '拉伸
  519. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Stretch
  520. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Stretch
  521. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.Fill
  522. FrmMain.ImgBack.Width = Double.NaN
  523. FrmMain.ImgBack.Height = Double.NaN
  524. Case 4 '平铺
  525. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Stretch
  526. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Stretch
  527. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  528. CType(FrmMain.ImgBack.Background, ImageBrush).TileMode = TileMode.Tile
  529. CType(FrmMain.ImgBack.Background, ImageBrush).Viewport = New Rect(0, 0, CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width, CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height)
  530. CType(FrmMain.ImgBack.Background, ImageBrush).ViewportUnits = BrushMappingMode.Absolute
  531. FrmMain.ImgBack.Width = Double.NaN
  532. FrmMain.ImgBack.Height = Double.NaN
  533. Case 5 '左上
  534. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Left
  535. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Top
  536. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  537. FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  538. FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  539. Case 6 '右上
  540. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Right
  541. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Top
  542. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  543. FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  544. FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  545. Case 7 '左下
  546. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Left
  547. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Bottom
  548. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  549. FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  550. FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  551. Case 8 '右下
  552. FrmMain.ImgBack.HorizontalAlignment = HorizontalAlignment.Right
  553. FrmMain.ImgBack.VerticalAlignment = VerticalAlignment.Bottom
  554. CType(FrmMain.ImgBack.Background, ImageBrush).Stretch = Stretch.None
  555. FrmMain.ImgBack.Width = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Width
  556. FrmMain.ImgBack.Height = CType(FrmMain.ImgBack.Background, ImageBrush).ImageSource.Height
  557. End Select
  558. End Sub
  559. '主页
  560. Public Sub UiCustomType(Value As Integer)
  561. If FrmSetupUI Is Nothing Then Return
  562. Select Case Value
  563. Case 0 '无
  564. FrmSetupUI.PanCustomPreset.Visibility = Visibility.Collapsed
  565. FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
  566. FrmSetupUI.PanCustomNet.Visibility = Visibility.Collapsed
  567. FrmSetupUI.HintCustom.Visibility = Visibility.Collapsed
  568. FrmSetupUI.HintCustomWarn.Visibility = Visibility.Collapsed
  569. Case 1 '本地
  570. FrmSetupUI.PanCustomPreset.Visibility = Visibility.Collapsed
  571. FrmSetupUI.PanCustomLocal.Visibility = Visibility.Visible
  572. FrmSetupUI.PanCustomNet.Visibility = Visibility.Collapsed
  573. FrmSetupUI.HintCustom.Visibility = Visibility.Visible
  574. FrmSetupUI.HintCustomWarn.Visibility = If(Setup.Get("HintCustomWarn"), Visibility.Collapsed, Visibility.Visible)
  575. FrmSetupUI.HintCustom.Text = $"从 PCL 文件夹下的 Custom.xaml 读取主页内容。{vbCrLf}你可以手动编辑该文件,向主页添加文本、图片、常用网站、快捷启动等功能。"
  576. FrmSetupUI.HintCustom.EventType = ""
  577. FrmSetupUI.HintCustom.EventData = ""
  578. Case 2 '联网
  579. FrmSetupUI.PanCustomPreset.Visibility = Visibility.Collapsed
  580. FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
  581. FrmSetupUI.PanCustomNet.Visibility = Visibility.Visible
  582. FrmSetupUI.HintCustom.Visibility = Visibility.Visible
  583. FrmSetupUI.HintCustomWarn.Visibility = If(Setup.Get("HintCustomWarn"), Visibility.Collapsed, Visibility.Visible)
  584. FrmSetupUI.HintCustom.Text = $"从指定网址联网获取主页内容。服主也可以用于动态更新服务器公告。{vbCrLf}如果你制作了稳定运行的联网主页,可以点击这条提示投稿,若合格即可加入预设!"
  585. FrmSetupUI.HintCustom.EventType = "打开网页"
  586. FrmSetupUI.HintCustom.EventData = "https://github.com/Hex-Dragon/PCL2/discussions/2528"
  587. Case 3 '预设
  588. FrmSetupUI.PanCustomPreset.Visibility = Visibility.Visible
  589. FrmSetupUI.PanCustomLocal.Visibility = Visibility.Collapsed
  590. FrmSetupUI.PanCustomNet.Visibility = Visibility.Collapsed
  591. FrmSetupUI.HintCustom.Visibility = Visibility.Collapsed
  592. FrmSetupUI.HintCustomWarn.Visibility = Visibility.Collapsed
  593. End Select
  594. FrmSetupUI.CardCustom.TriggerForceResize()
  595. End Sub
  596. '顶部栏
  597. Public Sub UiLogoType(Value As Integer)
  598. Select Case Value
  599. Case 0 '无
  600. FrmMain.ShapeTitleLogo.Visibility = Visibility.Collapsed
  601. FrmMain.LabTitleLogo.Visibility = Visibility.Collapsed
  602. FrmMain.ImageTitleLogo.Visibility = Visibility.Collapsed
  603. If Not IsNothing(FrmSetupUI) Then
  604. FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Visible
  605. FrmSetupUI.PanLogoText.Visibility = Visibility.Collapsed
  606. FrmSetupUI.PanLogoChange.Visibility = Visibility.Collapsed
  607. End If
  608. Case 1 '默认
  609. FrmMain.ShapeTitleLogo.Visibility = Visibility.Visible
  610. FrmMain.LabTitleLogo.Visibility = Visibility.Collapsed
  611. FrmMain.ImageTitleLogo.Visibility = Visibility.Collapsed
  612. If Not IsNothing(FrmSetupUI) Then
  613. FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Collapsed
  614. FrmSetupUI.PanLogoText.Visibility = Visibility.Collapsed
  615. FrmSetupUI.PanLogoChange.Visibility = Visibility.Collapsed
  616. End If
  617. Case 2 '文本
  618. FrmMain.ShapeTitleLogo.Visibility = Visibility.Collapsed
  619. FrmMain.LabTitleLogo.Visibility = Visibility.Visible
  620. FrmMain.ImageTitleLogo.Visibility = Visibility.Collapsed
  621. If Not IsNothing(FrmSetupUI) Then
  622. FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Collapsed
  623. FrmSetupUI.PanLogoText.Visibility = Visibility.Visible
  624. FrmSetupUI.PanLogoChange.Visibility = Visibility.Collapsed
  625. End If
  626. Setup.Load("UiLogoText", True)
  627. Case 3 '图片
  628. FrmMain.ShapeTitleLogo.Visibility = Visibility.Collapsed
  629. FrmMain.LabTitleLogo.Visibility = Visibility.Collapsed
  630. FrmMain.ImageTitleLogo.Visibility = Visibility.Visible
  631. If Not IsNothing(FrmSetupUI) Then
  632. FrmSetupUI.CheckLogoLeft.Visibility = Visibility.Collapsed
  633. FrmSetupUI.PanLogoText.Visibility = Visibility.Collapsed
  634. FrmSetupUI.PanLogoChange.Visibility = Visibility.Visible
  635. End If
  636. Try
  637. FrmMain.ImageTitleLogo.Source = Path & "PCL\Logo.png"
  638. Catch ex As Exception
  639. FrmMain.ImageTitleLogo.Source = Nothing
  640. Log(ex, "显示标题栏图片失败", LogLevel.Msgbox)
  641. End Try
  642. End Select
  643. Setup.Load("UiLogoLeft", True)
  644. If Not IsNothing(FrmSetupUI) Then FrmSetupUI.CardLogo.TriggerForceResize()
  645. End Sub
  646. Public Sub UiLogoText(Value As String)
  647. FrmMain.LabTitleLogo.Text = Value
  648. End Sub
  649. Public Sub UiLogoLeft(Value As Boolean)
  650. FrmMain.PanTitleMain.ColumnDefinitions(0).Width = New GridLength(If(Value AndAlso (Setup.Get("UiLogoType") = 0), 0, 1), GridUnitType.Star)
  651. End Sub
  652. '功能隐藏
  653. Public Sub UiHiddenPageLink(Value As Boolean)
  654. PageSetupUI.HiddenRefresh()
  655. End Sub
  656. Public Sub UiHiddenPageDownload(Value As Boolean)
  657. PageSetupUI.HiddenRefresh()
  658. End Sub
  659. Public Sub UiHiddenPageSetup(Value As Boolean)
  660. PageSetupUI.HiddenRefresh()
  661. End Sub
  662. Public Sub UiHiddenPageOther(Value As Boolean)
  663. PageSetupUI.HiddenRefresh()
  664. End Sub
  665. Public Sub UiHiddenFunctionSelect(Value As Boolean)
  666. PageSetupUI.HiddenRefresh()
  667. End Sub
  668. Public Sub UiHiddenFunctionModUpdate(Value As Boolean)
  669. PageSetupUI.HiddenRefresh()
  670. End Sub
  671. Public Sub UiHiddenFunctionHidden(Value As Boolean)
  672. PageSetupUI.HiddenRefresh()
  673. End Sub
  674. Public Sub UiHiddenSetupLaunch(Value As Boolean)
  675. PageSetupUI.HiddenRefresh()
  676. End Sub
  677. Public Sub UiHiddenSetupUi(Value As Boolean)
  678. PageSetupUI.HiddenRefresh()
  679. End Sub
  680. Public Sub UiHiddenSetupLink(Value As Boolean)
  681. PageSetupUI.HiddenRefresh()
  682. End Sub
  683. Public Sub UiHiddenSetupSystem(Value As Boolean)
  684. PageSetupUI.HiddenRefresh()
  685. End Sub
  686. Public Sub UiHiddenOtherHelp(Value As Boolean)
  687. PageSetupUI.HiddenRefresh()
  688. End Sub
  689. Public Sub UiHiddenOtherFeedback(Value As Boolean)
  690. PageSetupUI.HiddenRefresh()
  691. End Sub
  692. Public Sub UiHiddenOtherVote(Value As Boolean)
  693. PageSetupUI.HiddenRefresh()
  694. End Sub
  695. Public Sub UiHiddenOtherAbout(Value As Boolean)
  696. PageSetupUI.HiddenRefresh()
  697. End Sub
  698. Public Sub UiHiddenOtherTest(Value As Boolean)
  699. PageSetupUI.HiddenRefresh()
  700. End Sub
  701. #End Region
  702. #Region "System"
  703. '调试选项
  704. Public Sub SystemDebugMode(Value As Boolean)
  705. ModeDebug = Value
  706. End Sub
  707. Public Sub SystemDebugAnim(Value As Integer)
  708. AniSpeed = If(Value >= 30, 200, MathClamp(Value * 0.1 + 0.1, 0.1, 3))
  709. End Sub
  710. #End Region
  711. #Region "Version"
  712. '游戏内存
  713. Public Sub VersionRamType(Type As Integer)
  714. If FrmVersionSetup Is Nothing Then Return
  715. FrmVersionSetup.RamType(Type)
  716. End Sub
  717. '服务器
  718. Public Sub VersionServerLogin(Type As Integer)
  719. If FrmVersionSetup Is Nothing Then Return
  720. '为第三方登录清空缓存以更新描述
  721. WriteIni(PathMcFolder & "PCL.ini", "VersionCache", "")
  722. If PageVersionLeft.Version Is Nothing Then Return
  723. PageVersionLeft.Version = New McVersion(PageVersionLeft.Version.Name).Load()
  724. LoaderFolderRun(McVersionListLoader, PathMcFolder, LoaderFolderRunType.ForceRun, MaxDepth:=1, ExtraPath:="versions\")
  725. End Sub
  726. #End Region
  727. End Class