modMain.vb 156 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310
  1. Imports Ionic.Zip
  2. Public Module modMain
  3. #Region "声明"
  4. '常量
  5. Public Const VERSION_NAME As String = "1.0.9"
  6. Public Const VERSION_CODE As Integer = 52
  7. Public Const MC_VERSION_CODE As Integer = 7
  8. Public Const PUSH_VERSION_CODE As Integer = 2
  9. Public Const MAINFORM_HEIGHT As Integer = 435
  10. Public Const MAINFORM_WIDTH As Integer = 760
  11. Public Const MAINFORM_NAME As String = "Plain Craft Launcher"
  12. Public Const APPLICATION_SHORT_NAME As String = "PCL"
  13. Public Const APPLICATION_FULL_NAME As String = "Plain Craft Launcher"
  14. Public Const DOWNLOADING_END As String = ".PCLdownloading"
  15. Public Const TX_SREVER_1 As String = "http://pcl-1253424809.cosgz.myqcloud.com/"
  16. Public Const TX_SREVER_2 As String = "http://pcl-1254159202.costj.myqcloud.com/"
  17. Public Const QN_SERVER As String = "http://op7rrgq1p.bkt.clouddn.com/"
  18. Public MODE_DEBUG As Boolean = False
  19. Public MODE_OFFLINE As Boolean = False
  20. Public MODE_DEVELOPER As Boolean = False
  21. '各种路径
  22. ''' <summary>
  23. ''' 程序内嵌图片文件夹路径。
  24. ''' </summary>
  25. ''' <remarks></remarks>
  26. Public PATH_IMAGE As String = "pack://application:,,,/images/"
  27. ''' <summary>
  28. ''' 用户设置的下载文件夹路径。
  29. ''' </summary>
  30. ''' <remarks></remarks>
  31. Public PATH_DOWNLOAD As String
  32. ''' <summary>
  33. ''' Java路径。不包含“javaw.exe”,不以“\”结尾。
  34. ''' </summary>
  35. ''' <remarks></remarks>
  36. Public PATH_JAVA As String
  37. ''' <summary>
  38. ''' .minecraft 文件夹路径。以“\”结尾。
  39. ''' </summary>
  40. ''' <remarks></remarks>
  41. Public PATH_MC As String
  42. '窗体
  43. Public frmStart As formStart
  44. Public frmMain As New formMain
  45. Public frmHomeLeft As New formHomeLeft
  46. Public frmHomeRight As New formHomeRight
  47. Public frmDownloadLeft As New formDownloadLeft
  48. Public frmDownloadRight As New formDownloadRight
  49. Public frmSetup As formSetup
  50. '尚未使用的窗体
  51. Public frmManageLeft As formManageLeft
  52. Public frmManageRight As formManageLeft
  53. Public frmHelpLeft As formHelpLeft
  54. Public frmHelpRight As formHelpLeft
  55. '通用信息
  56. ''' <summary>
  57. ''' 是否正在显示蓝屏。
  58. ''' </summary>
  59. ''' <remarks></remarks>
  60. Public IsShowingDeathBlue As Boolean = False
  61. ''' <summary>
  62. ''' 是否启用基础控件动画。
  63. ''' </summary>
  64. ''' <remarks></remarks>
  65. Public UseControlAnimation As Boolean = False
  66. ''' <summary>
  67. ''' 程序加载耗时的计时器。
  68. ''' </summary>
  69. ''' <remarks></remarks>
  70. Public LoadTimeCost As Integer
  71. ''' <summary>
  72. ''' 正版登录结果。可以通过判断它是否为空来确定正版登录是否成功。
  73. ''' </summary>
  74. ''' <remarks></remarks>
  75. Public LoginResult As String = ""
  76. ''' <summary>
  77. ''' 所有Minecraft版本的列表。
  78. ''' </summary>
  79. ''' <remarks></remarks>
  80. Public VersionsList As New Dictionary(Of VersionSwapState, ArrayList) From {{VersionSwapState.UNKNOWN, New ArrayList}, {VersionSwapState.NORMAL, New ArrayList}, {VersionSwapState.SWAP, New ArrayList}, {VersionSwapState.OLD, New ArrayList}, {VersionSwapState.WRONG, New ArrayList}}
  81. Private _PathEnv As String = ""
  82. ''' <summary>
  83. ''' Path环境变量。
  84. ''' </summary>
  85. ''' <value></value>
  86. ''' <returns></returns>
  87. ''' <remarks></remarks>
  88. Public Property PathEnv As String
  89. Get
  90. If _PathEnv = "" Then _PathEnv = Environment.GetEnvironmentVariable("Path")
  91. Return _PathEnv
  92. End Get
  93. Set(ByVal value As String)
  94. _PathEnv = PathEnv
  95. End Set
  96. End Property
  97. ''' <summary>
  98. ''' 是否正在播放音乐。
  99. ''' </summary>
  100. ''' <remarks></remarks>
  101. Public IsPlayingMusic As Boolean = False
  102. ''' <summary>
  103. ''' 是否允许收集操作信息。
  104. ''' </summary>
  105. ''' <remarks></remarks>
  106. Public AllowFeedback As Boolean = True
  107. #End Region
  108. #Region "枚举"
  109. ''' <summary>
  110. ''' 加载状态,如加载中、成功、失败等。
  111. ''' </summary>
  112. ''' <remarks></remarks>
  113. Public Enum LoadState As Byte
  114. ''' <summary>
  115. ''' 尚未开始加载,正在等待
  116. ''' </summary>
  117. ''' <remarks></remarks>
  118. Waiting = 0
  119. ''' <summary>
  120. ''' 正在加载中
  121. ''' </summary>
  122. ''' <remarks></remarks>
  123. Loading = 1
  124. ''' <summary>
  125. ''' 加载成功
  126. ''' </summary>
  127. ''' <remarks></remarks>
  128. Loaded = 2
  129. ''' <summary>
  130. ''' 加载失败
  131. ''' </summary>
  132. ''' <remarks></remarks>
  133. Failed = 3
  134. End Enum
  135. ''' <summary>
  136. ''' 提示信息种类,如警告、完成、错误等。
  137. ''' </summary>
  138. ''' <remarks></remarks>
  139. Public Enum HintState As Integer
  140. ''' <summary>
  141. ''' 信息,通常是蓝色的“i”。
  142. ''' </summary>
  143. ''' <remarks></remarks>
  144. Info = 0
  145. ''' <summary>
  146. ''' 已完成,通常是绿色的“√”。
  147. ''' </summary>
  148. ''' <remarks></remarks>
  149. Finish = 1
  150. ''' <summary>
  151. ''' 警告,通常是黄色的“!”。
  152. ''' </summary>
  153. ''' <remarks></remarks>
  154. Warn = 2
  155. ''' <summary>
  156. ''' 错误,通常是红色的“×”。
  157. ''' </summary>
  158. ''' <remarks></remarks>
  159. Critical = 3
  160. End Enum
  161. ''' <summary>
  162. ''' Minecraft登陆方式。
  163. ''' </summary>
  164. ''' <remarks></remarks>
  165. Public Enum LoginMethods As Integer
  166. ''' <summary>
  167. ''' 离线。
  168. ''' </summary>
  169. ''' <remarks></remarks>
  170. Legacy = 0
  171. ''' <summary>
  172. ''' 正版登录。
  173. ''' </summary>
  174. ''' <remarks></remarks>
  175. Mojang = 1
  176. ''' <summary>
  177. ''' 未知。这用来标记未加载时的状态。
  178. ''' </summary>
  179. ''' <remarks></remarks>
  180. Unknown = 2
  181. End Enum
  182. ''' <summary>
  183. ''' Minecraft版本检查结果。
  184. ''' </summary>
  185. ''' <remarks></remarks>
  186. Public Enum VersionCheckState As Byte
  187. ''' <summary>
  188. ''' 尚未检查。
  189. ''' </summary>
  190. ''' <remarks></remarks>
  191. NOT_LOAD = 0
  192. ''' <summary>
  193. ''' 已经检查,没有问题。
  194. ''' </summary>
  195. ''' <remarks></remarks>
  196. NO_PROBLEM = 1
  197. ''' <summary>
  198. ''' 文件夹 或 Json与Jar 均不存在。
  199. ''' </summary>
  200. ''' <remarks></remarks>
  201. EMPTY_FOLDER = 2
  202. ''' <summary>
  203. ''' Json不存在,但是Jar存在。
  204. ''' </summary>
  205. ''' <remarks></remarks>
  206. JSON_NOT_EXIST = 3
  207. ''' <summary>
  208. ''' Json存在但是无法读取。
  209. ''' </summary>
  210. ''' <remarks></remarks>
  211. JSON_CANT_READ = 4
  212. ''' <summary>
  213. ''' 依赖版本文件夹不存在。
  214. ''' </summary>
  215. ''' <remarks></remarks>
  216. INHERITS_NOT_EXIST = 5
  217. ''' <summary>
  218. ''' 依赖版本检查出错。
  219. ''' </summary>
  220. ''' <remarks></remarks>
  221. INHERITS_EXCEPTION = 6
  222. ''' <summary>
  223. ''' Json存在,但是主要Jar不存在。
  224. ''' </summary>
  225. ''' <remarks></remarks>
  226. JAR_NOT_EXIST = 7
  227. End Enum
  228. ''' <summary>
  229. ''' Minecraft版本类型。
  230. ''' </summary>
  231. ''' <remarks></remarks>
  232. Public Enum MCVersionType As Byte
  233. ''' <summary>
  234. ''' 未获取版本或版本获取失败。
  235. ''' </summary>
  236. ''' <remarks></remarks>
  237. UNKNOWN = 0
  238. ''' <summary>
  239. ''' 快照和预览版。
  240. ''' </summary>
  241. ''' <remarks></remarks>
  242. SNAPSHOT = 1
  243. ''' <summary>
  244. ''' 正式版。
  245. ''' </summary>
  246. ''' <remarks></remarks>
  247. RELEASE = 2
  248. ''' <summary>
  249. ''' 愚人节版。
  250. ''' </summary>
  251. ''' <remarks></remarks>
  252. FOOL = 6
  253. ''' <summary>
  254. ''' OptiFine版。
  255. ''' </summary>
  256. ''' <remarks></remarks>
  257. OPTIFINE = 3
  258. ''' <summary>
  259. ''' Forge版。
  260. ''' </summary>
  261. ''' <remarks></remarks>
  262. FORGE = 4
  263. ''' <summary>
  264. ''' 发布时间在2012年及更早的版本。
  265. ''' </summary>
  266. ''' <remarks></remarks>
  267. OLD = 5
  268. End Enum
  269. ''' <summary>
  270. ''' 版本折叠分类。
  271. ''' </summary>
  272. ''' <remarks></remarks>
  273. Public Enum VersionSwapState As Byte
  274. ''' <summary>
  275. ''' 尚未确认。
  276. ''' </summary>
  277. ''' <remarks></remarks>
  278. UNKNOWN = 255
  279. ''' <summary>
  280. ''' 正常,无需折叠。
  281. ''' </summary>
  282. ''' <remarks></remarks>
  283. NORMAL = 0
  284. ''' <summary>
  285. ''' 折叠。
  286. ''' </summary>
  287. ''' <remarks></remarks>
  288. SWAP = 1
  289. ''' <summary>
  290. ''' 老版本。
  291. ''' </summary>
  292. ''' <remarks></remarks>
  293. OLD = 2
  294. ''' <summary>
  295. ''' 错误的版本。
  296. ''' </summary>
  297. ''' <remarks></remarks>
  298. WRONG = 3
  299. End Enum
  300. #End Region
  301. #Region "类"
  302. ''' <summary>
  303. ''' 提示信息种类转换。
  304. ''' </summary>
  305. ''' <remarks></remarks>
  306. Public Class HintConverter
  307. ''' <summary>
  308. ''' 提示信息文本。
  309. ''' </summary>
  310. ''' <remarks></remarks>
  311. Public Text As String
  312. ''' <summary>
  313. ''' 提示信息种类。
  314. ''' </summary>
  315. ''' <remarks></remarks>
  316. Public Type As HintState = 0
  317. Public Sub New(ByVal Text As String)
  318. Me.Text = Text
  319. End Sub
  320. Public Sub New(ByVal Text As String, ByVal Type As HintState)
  321. Me.Text = Text
  322. Me.Type = Type
  323. End Sub
  324. Public Shared Widening Operator CType(ByVal Text As String) As HintConverter
  325. Return New HintConverter(Text)
  326. End Operator
  327. Public Shared Widening Operator CType(ByVal Conv As HintConverter) As Color
  328. Select Case Conv.Type
  329. Case HintState.Info
  330. Return Color.FromRgb(26, 148, 252)
  331. Case HintState.Finish
  332. Return Color.FromRgb(29, 160, 29)
  333. Case HintState.Warn
  334. Return Color.FromRgb(216, 137, 8)
  335. Case Else
  336. Return Color.FromRgb(255, 46, 0)
  337. End Select
  338. End Operator
  339. Public Shadows Function ToString() As String
  340. Return "[" & {"Hint", "Finish", "Warn", "Critical"}(Type) & "] " & Text
  341. End Function
  342. ''' <summary>
  343. ''' 获取目前提示种类的英文名。
  344. ''' </summary>
  345. ''' <returns>提示种类的英文名,如“Critical”。</returns>
  346. ''' <remarks></remarks>
  347. Public Function GetTypeName() As String
  348. Return HintState.GetName(Type.GetType, Type)
  349. End Function
  350. End Class
  351. ''' <summary>
  352. ''' 一个不包含UI支持库的Minecraft版本类。
  353. ''' </summary>
  354. ''' <remarks></remarks>
  355. Public Class MCVersion
  356. Implements IComparable(Of MCVersion)
  357. ''' <summary>
  358. ''' 这些版本信息是否都是从已经配置好的文件中读取的。
  359. ''' </summary>
  360. ''' <remarks></remarks>
  361. Public LoadedByFile As Boolean = True
  362. ''' <summary>
  363. ''' 版本折叠分类。
  364. ''' </summary>
  365. ''' <remarks></remarks>
  366. Public SwapType As VersionSwapState = VersionSwapState.UNKNOWN
  367. ''' <summary>
  368. ''' 对应的Minecraft版本。这与Forge等无关。
  369. ''' </summary>
  370. ''' <remarks></remarks>
  371. Public Version As String = "未知"
  372. ''' <summary>
  373. ''' 版本的发布时间。用于鉴别版本号。
  374. ''' </summary>
  375. ''' <remarks></remarks>
  376. Public ReleaseTime As String = "1970-01-01T00:00:00"
  377. ''' <summary>
  378. ''' 主版本号(如1.9.2的9)。快照版为0。
  379. ''' </summary>
  380. ''' <remarks></remarks>
  381. Public MainVersionCode As Integer = 0
  382. ''' <summary>
  383. ''' Minecraft版本种类。
  384. ''' </summary>
  385. ''' <remarks></remarks>
  386. Public Type As MCVersionType = MCVersionType.UNKNOWN
  387. ''' <summary>
  388. ''' Logo的内容。用于ListItem显示。
  389. ''' </summary>
  390. ''' <remarks></remarks>
  391. Public Logo As String = PATH_IMAGE & "Block-Grass.png"
  392. ''' <summary>
  393. ''' 描述内容。用于ListItem显示。
  394. ''' </summary>
  395. ''' <remarks></remarks>
  396. Public Description As String = ""
  397. ''' <summary>
  398. ''' 版本检查结果。在检查版本时完成。
  399. ''' </summary>
  400. ''' <remarks></remarks>
  401. Public VersionCheckResult As VersionCheckState = VersionCheckState.NOT_LOAD
  402. ''' <summary>
  403. ''' 该版本的依赖版本。在检查版本时完成。
  404. ''' </summary>
  405. ''' <remarks></remarks>
  406. Public InheritVersion As String = ""
  407. ''' <summary>
  408. ''' 该版本的资源文件号。在检查版本时完成。
  409. ''' </summary>
  410. ''' <remarks></remarks>
  411. Public Assets As String
  412. '自处理属性
  413. ''' <summary>
  414. ''' 文件夹名称,或者说是这个版本的名称。
  415. ''' </summary>
  416. ''' <remarks></remarks>
  417. Public Name As String
  418. Private _Json As JObject
  419. ''' <summary>
  420. ''' Json对象。
  421. ''' </summary>
  422. ''' <value></value>
  423. ''' <returns></returns>
  424. ''' <remarks></remarks>
  425. Public ReadOnly Property Json As JObject
  426. Get
  427. If IsNothing(_Json) Then ReadJson()
  428. Return If(_JsonText = "ERROR", "", _Json)
  429. End Get
  430. End Property
  431. Private _JsonText As String = ""
  432. ''' <summary>
  433. ''' Json文件的内容。
  434. ''' </summary>
  435. ''' <remarks></remarks>
  436. Public ReadOnly Property JsonText As String
  437. Get
  438. If _JsonText = "" Then ReadJson()
  439. Return If(_JsonText = "ERROR", "", _JsonText)
  440. End Get
  441. End Property
  442. ''' <summary>
  443. ''' 完整的文件夹地址。以“\”结尾。
  444. ''' </summary>
  445. ''' <remarks></remarks>
  446. Public ReadOnly Property Path As String
  447. Get
  448. If Name = "" Then Throw New Exception("没有指定本版本的文件夹。")
  449. Return PATH_MC & "versions\" & Name & "\"
  450. End Get
  451. End Property
  452. '事件
  453. Public Sub New(ByVal FolderName As String)
  454. Name = FolderName
  455. End Sub
  456. Private Sub ReadJson()
  457. '读取Json
  458. For Each Encode As Encoding In {Encoding.Default, Encoding.Unicode, New UTF8Encoding(False), Encoding.ASCII}
  459. Try
  460. _JsonText = ReadFileToEnd(Path & Name & ".json", Encode)
  461. If _JsonText = "" Then GoTo Fail
  462. _Json = CType(Newtonsoft.Json.JsonConvert.DeserializeObject(_JsonText), JObject)
  463. Exit Sub
  464. Catch
  465. '编码错误
  466. _JsonText = "ERROR"
  467. End Try
  468. NextFormat:
  469. Next
  470. Fail:
  471. '各种编码都没戏了
  472. log("[System] Json文件读取失败:" & Path & Name & ".json", True)
  473. Throw New FileFormatException("Json文件读取失败:" & Path & Name & ".json")
  474. End Sub
  475. Public Overrides Function ToString() As String
  476. Return Name & " / " & GetStringFromEnum(SwapType) & If(Version = Name, "", " / " & Version) & If(VersionCheckResult = VersionCheckState.NO_PROBLEM, "", " / " & GetStringFromEnum(VersionCheckResult))
  477. End Function
  478. Public Overloads Function CompareTo(ByVal Other As MCVersion) As Integer Implements IComparable(Of MCVersion).CompareTo
  479. If IsNothing(Other) Then Return 1
  480. Return String.Compare(Me.Name, Other.Name)
  481. End Function
  482. End Class
  483. #End Region
  484. #Region "登录"
  485. ''' <summary>
  486. ''' 进行Login方式的正版登录。
  487. ''' </summary>
  488. ''' <param name="Email">邮箱地址。</param>
  489. ''' <param name="Pass">明文密码。</param>
  490. ''' <returns></returns>
  491. ''' <remarks></remarks>
  492. Public Function OnlineLogin(ByVal Email As String, ByVal Pass As String) As String
  493. '没联网登录个毛哦
  494. If MODE_OFFLINE Then Throw New WebException("没有网络连接,无法登录!")
  495. '尝试登录
  496. Try
  497. log("[System] 正版登录(Login):" & Email)
  498. Dim request As WebRequest = WebRequest.Create("https://authserver.mojang.com/authenticate")
  499. request.Method = "POST"
  500. Dim postData As String = "{""agent"": {""name"": ""Minecraft"",""version"": 1},""username"":""" & Email & """,""password"":""" & Pass & """,""requestUser"":true}"
  501. Dim byteArray As Byte() = New UTF8Encoding(False).GetBytes(postData)
  502. request.ContentType = "application/json; charset=utf-8"
  503. request.ContentLength = byteArray.Length
  504. request.Timeout = 20000
  505. Dim dataStream As Stream = request.GetRequestStream()
  506. dataStream.Write(byteArray, 0, byteArray.Length)
  507. dataStream.Close()
  508. Dim response As WebResponse = request.GetResponse()
  509. dataStream = response.GetResponseStream()
  510. Dim reader As New StreamReader(dataStream)
  511. Dim responseFromServer As String = reader.ReadToEnd()
  512. OnlineLogin = responseFromServer
  513. '输出信息
  514. Dim LoginJson = CType(Newtonsoft.Json.JsonConvert.DeserializeObject(OnlineLogin), JObject)
  515. WriteReg("AccessToken", SerAdd(LoginJson("accessToken").ToString))
  516. WriteReg("ClientToken", SerAdd(LoginJson("clientToken").ToString))
  517. WriteReg("MojangPlayerName", LoginJson("selectedProfile")("name").ToString)
  518. WriteReg("MojangPlayerUUID", LoginJson("selectedProfile")("id").ToString)
  519. log("[System] 正版登录成功")
  520. reader.Close()
  521. dataStream.Dispose()
  522. response.Close()
  523. Catch ex As Exception
  524. ExShow(ex, "正版登录失败", ErrorLevel.Slient)
  525. If ex.Message.Contains("403") Then
  526. Throw New WebException("正版登录失败,请检查你的邮箱和密码是否正确或等待5分钟再试!")
  527. Else
  528. Throw New WebException("正版登录失败!" & vbCrLf & "详细的错误信息:" & ex.Message)
  529. End If
  530. End Try
  531. End Function
  532. ''' <summary>
  533. ''' 进行Refresh方式的正版登录。
  534. ''' </summary>
  535. ''' <param name="AccessToken">在Login登录中存储的AccessToken。</param>
  536. ''' <param name="ClientToken">在Login登录中存储的ClientToken。</param>
  537. ''' <returns></returns>
  538. ''' <remarks></remarks>
  539. Public Function RefreshLogin(ByVal AccessToken As String, ByVal ClientToken As String) As String
  540. '没联网登录个毛哦
  541. If MODE_OFFLINE Then Throw New WebException("没有网络连接,无法登录!")
  542. '尝试登录
  543. Try
  544. log("[System] 刷新正版登录")
  545. Dim request As WebRequest = WebRequest.Create("https://authserver.mojang.com/refresh")
  546. request.Method = "POST"
  547. Dim postData As String = "{""accessToken"":""" & AccessToken & """,""clientToken"":""" & ClientToken & """}"
  548. Dim byteArray As Byte() = New UTF8Encoding(False).GetBytes(postData)
  549. request.ContentType = "application/json; charset=utf-8"
  550. request.ContentLength = byteArray.Length
  551. request.Timeout = 20000
  552. Dim dataStream As Stream = request.GetRequestStream()
  553. dataStream.Write(byteArray, 0, byteArray.Length)
  554. dataStream.Close()
  555. Dim response As WebResponse = request.GetResponse()
  556. dataStream = response.GetResponseStream()
  557. Dim reader As New StreamReader(dataStream)
  558. Dim responseFromServer As String = reader.ReadToEnd()
  559. RefreshLogin = responseFromServer
  560. '输出信息
  561. Dim LoginJson = CType(Newtonsoft.Json.JsonConvert.DeserializeObject(RefreshLogin), JObject)
  562. WriteReg("AccessToken", SerAdd(LoginJson("accessToken").ToString))
  563. WriteReg("ClientToken", SerAdd(LoginJson("clientToken").ToString))
  564. WriteReg("MojangPlayerName", LoginJson("selectedProfile")("name").ToString)
  565. WriteReg("MojangPlayerUUID", LoginJson("selectedProfile")("id").ToString)
  566. log("[System] 刷新正版登录成功")
  567. reader.Close()
  568. dataStream.Dispose()
  569. response.Close()
  570. Catch ex As Exception
  571. ExShow(ex, "刷新正版登录失败", ErrorLevel.Slient)
  572. Throw New WebException("刷新正版登录失败!" & vbCrLf & "详细的错误信息:" & ex.Message)
  573. End Try
  574. End Function
  575. #End Region
  576. #Region "线程池"
  577. Public PoolCount As Integer = 0 '目前运行中的线程计数
  578. Public Const POOL_MAXCOUNT As Integer = 15 '最大线程数
  579. Public Pool As New ArrayList '线程池
  580. Public Sub PoolLoader()
  581. On Error Resume Next
  582. Do While True
  583. If Pool.Count > 0 Then
  584. ReSearch:
  585. For i = 0 To Pool.Count - 1
  586. If IsNothing(Pool(i)) Then
  587. Pool.RemoveAt(i)
  588. Exit For
  589. End If
  590. Select Case Pool(i).ThreadState
  591. Case System.Threading.ThreadState.Unstarted
  592. If PoolCount < POOL_MAXCOUNT Then
  593. '线程尚未启动
  594. Pool(i).Start()
  595. PoolCount = PoolCount + 1
  596. End If
  597. Case System.Threading.ThreadState.Stopped, System.Threading.ThreadState.Aborted
  598. '线程已经停止
  599. PoolCount = PoolCount - 1
  600. Pool.RemoveAt(i)
  601. i = i - 1
  602. End Select
  603. If i >= Pool.Count - 1 Then Exit For
  604. Next i
  605. End If
  606. Thread.Sleep(20)
  607. Loop
  608. End Sub
  609. ''' <summary>
  610. ''' 加载线程:Java文件夹检测。它会检测PATH_JAVA的值,如果无Java则初始化。
  611. ''' </summary>
  612. ''' <remarks></remarks>
  613. Public Sub PoolJavaFolder(IsJustFind As Boolean)
  614. '初始化
  615. PATH_JAVA = If(IsJustFind, "", ReadReg("SetupJavaPath"))
  616. Try
  617. '如果注册表已经存在 Java 的正确路径就结束
  618. Dim Env As String = PathEnv
  619. If File.Exists(PATH_JAVA & "\javaw.exe") And (File.Exists(PATH_JAVA & "\jli.dll") Or PATH_JAVA.Contains("javapath")) Then
  620. log("[Pool] Java 路径:" & PATH_JAVA)
  621. Exit Sub
  622. End If
  623. '检查环境变量中的 Java
  624. Dim EachPath As String() = Split(Env, ";")
  625. For Each PathFind As String In EachPath
  626. '格式化字符串,保证不以“\”结尾
  627. If PathFind.EndsWith("\") Then PathFind = Left(PathFind, Len(PathFind) - 1)
  628. '检查有效性
  629. If File.Exists(PathFind & "\javaw.exe") And (File.Exists(PathFind & "\jli.dll") Or PathFind.Contains("javapath")) Then
  630. PATH_JAVA = PathFind
  631. log("[Pool] 环境变量中找到 Java:" & PATH_JAVA)
  632. WriteReg("SetupJavaPath", PATH_JAVA)
  633. Exit Sub
  634. End If
  635. Next
  636. '人工查找
  637. log("[Pool] 遍历寻找 Java 开始")
  638. Dim Result As String
  639. '循环每个盘
  640. For Each Disk As DriveInfo In DriveInfo.GetDrives()
  641. Result = SearchJava(Disk.Name)
  642. '如果找到了的话就跳出,并且设置环境变量
  643. If Not Result = "" Then
  644. PATH_JAVA = Mid(Result, 1, Result.LastIndexOf("\"))
  645. GoTo FinishSearch
  646. End If
  647. Next
  648. '查找当前启动器目录
  649. Result = SearchJava(PATH, True)
  650. If Not Result = "" Then
  651. PATH_JAVA = Mid(Result, 1, Result.LastIndexOf("\"))
  652. GoTo FinishSearch
  653. End If
  654. '人工查找失败
  655. log("[Pool] 遍历寻找 Java 失败")
  656. PATH_JAVA = ""
  657. ShowHint(New HintConverter("未找到可用的 Java", HintState.Warn))
  658. Exit Sub
  659. Catch ex As Exception
  660. ExShow(ex, "查找 Java 时出错", ErrorLevel.MsgboxAndFeedback)
  661. End Try
  662. FinishSearch:
  663. If Not IsJustFind Then SetJavaEnvironment()
  664. End Sub
  665. ''' <summary>
  666. ''' 检查指定路径下的文件夹并且模糊搜索Java。这不会搜索全部路径。
  667. ''' </summary>
  668. ''' <param name="path">开始搜索的起始路径</param>
  669. ''' <param name="fullSearch">搜索当前文件夹下的全部文件夹(这不会传递到子级文件夹)</param>
  670. ''' <returns>搜索到的Java路径,如果失败则为空</returns>
  671. ''' <remarks></remarks>
  672. Private Function SearchJava(ByVal path As String, Optional ByVal fullSearch As Boolean = False) As String
  673. Try
  674. SearchJava = ""
  675. Dim AllPath() As String
  676. Dim LastEntry As String '文件夹或文件名
  677. If Directory.Exists(path) Then
  678. '该目录存在
  679. AllPath = Directory.GetFileSystemEntries(path)
  680. For Each Entry As String In AllPath
  681. LastEntry = Entry.Split("\")(Entry.Split("\").Length - 1) '获取文件夹或文件名
  682. Dim SearchEntry = LastEntry.ToLower.Replace(" ", "") '用于搜索的字符串
  683. If fullSearch Or SearchEntry.Contains("java") Or SearchEntry.Contains("jdk") Or SearchEntry.Contains("jre") Or SearchEntry.Contains("bin") Or SearchEntry.Contains("mc") Or SearchEntry.Contains("minecraft") Or SearchEntry.Contains("program") Or SearchEntry.Contains("我的世界") Or SearchEntry.Contains("net") Or SearchEntry.Contains("runtime") Or SearchEntry.Contains("oracle") Or SearchEntry.Contains("1.") Or SearchEntry.Contains("启") Then
  684. If File.Exists(Entry) Then
  685. '如果是文件
  686. If LastEntry = "javaw.exe" And File.Exists(Mid(Entry, 1, Entry.LastIndexOf("\")) & "\jli.dll") Then
  687. '找到Java
  688. SearchJava = Entry
  689. Exit For
  690. End If
  691. ElseIf Directory.Exists(Entry) Then
  692. '如果是文件夹
  693. Dim Result As String = SearchJava(Entry)
  694. If Not Result = "" Then Return Result
  695. End If
  696. End If
  697. Next
  698. End If
  699. Catch ex As Exception
  700. ExShow(ex, "遍历查找Java时出错", ErrorLevel.Slient)
  701. '防止无文件夹权限而导致崩溃
  702. SearchJava = ""
  703. End Try
  704. End Function
  705. ''' <summary>
  706. ''' 加载线程:Minecraft文件夹检测。
  707. ''' </summary>
  708. ''' <remarks></remarks>
  709. Public Sub PoolMinecraftFolder()
  710. Try
  711. '等待版本列表加载结束
  712. Do While IsPoolVersionListRunning
  713. Thread.Sleep(25)
  714. Loop
  715. Dim MojangPath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\.minecraft\"
  716. Dim AllFoldersList As New ArrayList
  717. '加载可用文件夹地址
  718. Dim AllFolders As String = ReadIni("setup", "LaunchFolders", "")
  719. If Not AllFolders = "" Then
  720. '如果存在可用文件夹地址,则再次检查它们
  721. Dim NewFolderList As New ArrayList
  722. For Each Dir As String In AllFolders.Split("|")
  723. If CheckDirectoryPermission(Dir) Then
  724. NewFolderList.Add(Dir)
  725. AllFoldersList.Add(Dir)
  726. End If
  727. Next
  728. AllFolders = Join(NewFolderList.ToArray, "|")
  729. WriteIni("setup", "LaunchFolders", AllFolders)
  730. End If
  731. '加载设置中的Minecraft文件夹地址
  732. PATH_MC = ReadIni("setup", "LaunchFolderSelect", "")
  733. If CheckDirectoryPermission(MojangPath & "versions\") Then
  734. If Not Directory.GetDirectories(MojangPath & "versions\").Length = 0 Then AllFoldersList.Add(MojangPath)
  735. End If
  736. '如果为当前目录则自动创建
  737. If PATH_MC = PATH & ".minecraft\" Then
  738. If Not CheckDirectoryPermission(PATH_MC) Then
  739. Directory.CreateDirectory(PATH_MC)
  740. Directory.CreateDirectory(PATH_MC & "versions\")
  741. End If
  742. GoTo FinishMinecraftFolderCheck
  743. End If
  744. '如果在可用文件夹列表且有效则结束
  745. If AllFoldersList.Contains(PATH_MC) And CheckDirectoryPermission(PATH_MC) Then GoTo FinishMinecraftFolderCheck
  746. '如果是用户设置的路径,则显示一个通知
  747. If Not PATH_MC = "" Then ShowHint("原先的 Minecraft 文件夹路径已失效:" & PATH_MC)
  748. '优先尝试设置为当前文件夹
  749. If CheckDirectoryPermission(PATH & ".minecraft\versions") Then
  750. PATH_MC = PATH & ".minecraft\"
  751. GoTo FinishMinecraftFolderCheck
  752. End If
  753. '优先尝试设置为官启文件夹
  754. If AllFoldersList.Contains(MojangPath) Then
  755. If MyMsgbox("官方启动器的 Minecraft 文件夹下存在 " & Directory.GetDirectories(MojangPath & "versions").Length & " 个版本,是否使用官方启动器的文件夹?" & vbCrLf & "你可以在设置页面更改这个设置。", "Minecraft 文件夹确认", "确定", "取消") = 1 Then
  756. '使用官启文件夹
  757. PATH_MC = MojangPath
  758. GoTo FinishMinecraftFolderCheck
  759. End If
  760. End If
  761. AllFoldersList.Remove(MojangPath)
  762. '从列表中查找新的目录
  763. For Each Dir As String In AllFolders.Split("|")
  764. If CheckDirectoryPermission(Dir) Then
  765. PATH_MC = Dir
  766. GoTo FinishMinecraftFolderCheck
  767. End If
  768. Next
  769. '执行到这里就需要创建一个新的.minecraft文件夹了
  770. PATH_MC = PATH & ".minecraft\"
  771. Directory.CreateDirectory(PATH_MC)
  772. Directory.CreateDirectory(PATH_MC & "versions\")
  773. FinishMinecraftFolderCheck:
  774. log("[Pool] .minecraft文件夹:" & PATH_MC)
  775. WriteIni("setup", "LaunchFolderSelect", PATH_MC)
  776. '输出启动器信息
  777. If Not File.Exists(PATH_MC & "launcher_profiles.json") Then
  778. WriteFile(PATH_MC & "launcher_profiles.json",
  779. "{" & vbCrLf &
  780. " ""profiles"": {" & vbCrLf &
  781. " """ & APPLICATION_SHORT_NAME & """: {" & vbCrLf &
  782. " ""name"": """ & APPLICATION_SHORT_NAME & """," & vbCrLf &
  783. " }," & vbCrLf &
  784. " ""(Default)"": {" & vbCrLf &
  785. " ""name"": ""(" & APPLICATION_SHORT_NAME & ")""" & vbCrLf &
  786. " }" & vbCrLf &
  787. " }," & vbCrLf &
  788. " ""selectedProfile"": ""(Default)""," & vbCrLf &
  789. " ""clientToken"": ""88888888-8888-8888-8888-888888888888""" & vbCrLf &
  790. "}")
  791. log("[Pool] 已创建 launcher_profiles.json")
  792. End If
  793. If Not File.Exists(PATH_MC & "options.txt") Then
  794. WriteFile(PATH_MC & "options.txt", "lang:zh_cn" & vbCrLf)
  795. log("[Pool] 已创建 options.txt")
  796. End If
  797. '继续加载版本列表
  798. Pool.Add(New Thread(AddressOf PoolVersionList))
  799. Catch ex As Exception
  800. ExShow(ex, "检测MC文件夹失败", ErrorLevel.MsgboxAndFeedback)
  801. End Try
  802. End Sub
  803. Private PoolLoginLock As New Object
  804. ''' <summary>
  805. ''' 加载线程:自动登录。
  806. ''' </summary>
  807. ''' <remarks></remarks>
  808. Public Sub PoolLogin(IsAutoLogin As Boolean)
  809. Try
  810. If MODE_OFFLINE Then Exit Sub
  811. SyncLock PoolLoginLock
  812. If (Not ReadReg("Email").Contains("@")) Or (Len(ReadReg("Password")) < 4) Or (IsAutoLogin And ReadReg("HomeSave", "True") = "False") Then GoTo ExitSub
  813. frmHomeRight.StartButtonIsLogining = True
  814. '尝试登录
  815. If ReadReg("ClientToken") = "" Then
  816. PoolLoginRun(New LoginInfo With {.IsRefresh = False, .Email = ReadReg("Email"), .Password = SerRemove(ReadReg("Password"))}, True)
  817. Else
  818. If Not PoolLoginRun(New LoginInfo With {.IsRefresh = True, .AccessToken = SerRemove(ReadReg("AccessToken")), .ClientToken = SerRemove(ReadReg("ClientToken"))}, False) Then
  819. PoolLoginRun(New LoginInfo With {.IsRefresh = False, .Email = ReadReg("Email"), .Password = SerRemove(ReadReg("Password"))}, True)
  820. End If
  821. End If
  822. ExitSub:
  823. frmHomeRight.StartButtonIsLogining = False
  824. End SyncLock
  825. '加载皮肤
  826. If LoginResult.Contains("selectedProfile") Then
  827. Dim UUID As String = CType(Newtonsoft.Json.JsonConvert.DeserializeObject(LoginResult), JObject)("selectedProfile")("id").ToString
  828. WriteIni("cache\skin\UUID", CType(Newtonsoft.Json.JsonConvert.DeserializeObject(LoginResult), JObject)("selectedProfile")("name").ToString, UUID)
  829. Dim SkinAddress As String = DownloadSkin(UUID)
  830. If Not SkinAddress = "" Then frmMain.Dispatcher.Invoke(Sub() frmHomeRight.LoadMojangSkin(SkinAddress))
  831. End If
  832. Catch ex As Exception
  833. frmHomeRight.StartButtonIsLogining = False
  834. ExShow(ex, "自动登录出错", ErrorLevel.MsgboxAndFeedback)
  835. End Try
  836. End Sub
  837. ''' <summary>
  838. ''' 进行正版登录所需的信息包。
  839. ''' </summary>
  840. ''' <remarks></remarks>
  841. Public Structure LoginInfo
  842. Public IsRefresh As Boolean
  843. Public Email As String
  844. Public Password As String
  845. Public AccessToken As String
  846. Public ClientToken As String
  847. End Structure
  848. ''' <summary>
  849. ''' 按照给定的方式进行登录尝试。
  850. ''' </summary>
  851. ''' <remarks></remarks>
  852. Private Function PoolLoginRun(ByVal Info As LoginInfo, ByVal IsShowHint As Boolean) As Boolean
  853. '正版登录
  854. Try
  855. log("[Poll] 登录开始")
  856. If Info.IsRefresh Then
  857. LoginResult = RefreshLogin(Info.AccessToken, Info.ClientToken)
  858. Else
  859. LoginResult = OnlineLogin(Info.Email, Info.Password)
  860. End If
  861. log("[Poll] 登录成功")
  862. Return True
  863. Catch ex As Exception
  864. ExShow(ex, "登录失败")
  865. If IsShowHint Then ShowHint(New HintConverter(GetStringFromException(ex), HintState.Warn))
  866. LoginResult = ""
  867. Return False
  868. End Try
  869. End Function
  870. Public NeedUpdate As LoadState = LoadState.Waiting
  871. ''' <summary>
  872. ''' 加载线程:自动更新。
  873. ''' </summary>
  874. ''' <remarks></remarks>
  875. Public Sub PoolUpdate()
  876. If MODE_OFFLINE Then NeedUpdate = LoadState.Failed : Exit Sub
  877. '更新
  878. Try
  879. NeedUpdate = LoadState.Loading
  880. Dim data As String = GetWebsiteCode(TX_SREVER_1 & "update" & If(ReadIni("setup", "SysUpdateTest", "False"), "_snapshot", "_release") & ".ini", Encoding.Default)
  881. If Not data.Contains("VersionCode") Then
  882. Throw New Exception("获取自动更新网页代码失败。")
  883. Exit Sub
  884. End If
  885. WriteFile("PCL\update.ini", data, , , False)
  886. '检查更新
  887. Dim newVersionCode As Integer = ReadIni(PATH & "PCL\update.ini", "VersionCode", "0")
  888. '为了避免在首次打开时自动更新到 PCL2,这一段暂时注释了
  889. 'If newVersionCode > VERSION_CODE Then
  890. ' NeedUpdate = LoadState.Loaded
  891. ' If ReadIni("setup", "SysUpdate", "True") = "False" Then GoTo NoHint '设置为不检查更新
  892. ' log("[Pool] 发现新版本(" & newVersionCode & ")")
  893. ' '更新可用
  894. ' If ReadIni("setup", "SysUpdateHint", "True") Then
  895. ' '提示更新
  896. ' frmHomeRight.Dispatcher.Invoke(Sub() frmHomeRight.ShowUpdate("发现启动器更新:" & ReadIni("update", "Version", "未知版本"), formHomeRight.UpdateType.PCL))
  897. ' Else
  898. ' '自动开始更新
  899. ' ShowHint("正在自动更新,更新结束后 PCL 将会自动重启")
  900. ' Dim th As New Thread(AddressOf DownloadUpdate)
  901. ' th.Start()
  902. ' End If
  903. 'Else
  904. NeedUpdate = LoadState.Failed
  905. Log("[Pool] 已经是最新版本(" & newVersionCode & ")")
  906. 'End If
  907. NoHint:
  908. Catch ex As Exception
  909. NeedUpdate = LoadState.Failed
  910. ExShow(ex, "检查更新失败")
  911. '更新检测失败
  912. Dim th As New Thread(Sub()
  913. log("[Pool] 开始测试服务器 Ping")
  914. Try
  915. log("[Pool] Ping 测试成功:" & Ping(TX_SREVER_1, 10000) & "ms")
  916. Catch exx As Exception
  917. ExShow(exx, "无法连接至 PCL 服务器")
  918. End Try
  919. End Sub)
  920. th.Start()
  921. End Try
  922. '通知
  923. Dim newNotice As Integer = ReadIni(PATH & "PCL\update.ini", "Notice", "0")
  924. Dim currentNotice As Integer = ReadIni("setup", "Notice", "0")
  925. If newNotice > currentNotice Then
  926. Try
  927. log("[Pool] 发现公告(" & newNotice & ")")
  928. Dim Notices As JObject = ReadJson(GetWebsiteCode(TX_SREVER_1 & "notice.json", Encoding.Default))
  929. For Each Notice As JToken In Notices("all")
  930. If Val(Notice("id")) > currentNotice Then
  931. '确认要求
  932. For Each Require As JToken In If(Notice("require"), {})
  933. Select Case Require("type").ToString
  934. Case "open_count_min"
  935. '{"type":"open_count_min","value":50}
  936. If Val(ReadIni("setup", "Count", "0")) < Val(Require("value")) Then SendStat("公告", "跳过", Notice("id")) : GoTo NextNotice
  937. Case "open_count_max"
  938. '{"type":"open_count_max","value":55}
  939. If Val(ReadIni("setup", "Count", "0")) > Val(Require("value")) Then SendStat("公告", "跳过", Notice("id")) : GoTo NextNotice
  940. Case "version_code_min"
  941. '{"type":"version_code_min","value":5}
  942. If VERSION_CODE < Val(Require("value")) Then SendStat("公告", "跳过", Notice("id")) : GoTo NextNotice
  943. Case "version_code_max"
  944. '{"type":"version_code_max","value":10}
  945. If VERSION_CODE > Val(Require("value")) Then SendStat("公告", "跳过", Notice("id")) : GoTo NextNotice
  946. End Select
  947. Next
  948. '初始化
  949. SendStat("公告", "显示", Notice("id"))
  950. Dim Arguments() As String = Notice("text").ToString.Split("|")
  951. '确认类型
  952. Select Case Notice("type").ToString
  953. Case "msgbox"
  954. '弹窗
  955. '"text":"弹窗测试标题|弹窗测试内容\n第二行|知道啦"
  956. MyMsgbox(Arguments(1), Arguments(0).Replace("\n", vbCrLf), Arguments(2))
  957. Case "url"
  958. '可选调用URL
  959. '"text":"网页测试标题|网页测试\n第二行|知道啦|不打开|http://www.mcbbs.net/"
  960. If MyMsgbox(Arguments(1), Arguments(0).Replace("\n", vbCrLf), Arguments(2), Arguments(3)) = 1 Then
  961. Process.Start(Arguments(4))
  962. End If
  963. Case "update"
  964. '要求更新
  965. '"text":"更新测试标题|更新测试\n第二行|知道啦|打死不更新"
  966. If NeedUpdate Then
  967. If MyMsgbox(Arguments(1), Arguments(0).Replace("\n", vbCrLf), Arguments(2), Arguments(3)) = 1 Then
  968. frmMain.Dispatcher.Invoke(Sub()
  969. ShowHint("正在更新,更新结束后 PCL 将会自动重启")
  970. Dim th As New Thread(AddressOf DownloadUpdate)
  971. th.Start()
  972. AniStart({
  973. AaHeight(frmHomeRight.panLaunch, 277 - frmHomeRight.panLaunch.Height, , , New AniEaseEnd),
  974. AaOpacity(frmHomeRight.btnUpdate, -frmHomeRight.btnUpdate.Opacity, 200)
  975. }, "HomeRightHideUpdate")
  976. End Sub)
  977. End If
  978. End If
  979. End Select
  980. End If
  981. NextNotice:
  982. Next
  983. WriteIni("setup", "Notice", newNotice)
  984. Catch ex As Exception
  985. ExShow(ex, "处理公告失败")
  986. End Try
  987. End If
  988. End Sub
  989. Public IsPoolVersionListRunning As Boolean = False
  990. ''' <summary>
  991. ''' 加载线程:加载版本列表。
  992. ''' </summary>
  993. ''' <remarks></remarks>
  994. Public Sub PoolVersionList()
  995. '保证不同时加载版本列表
  996. Do While IsPoolVersionListRunning
  997. Thread.Sleep(RandomInteger(15, 65))
  998. Loop
  999. IsPoolVersionListRunning = True
  1000. frmHomeRight.StartButtonIsLoading = True
  1001. Try
  1002. log("[Pool] 预加载版本列表开始")
  1003. Dim ReloadAll As Boolean = False '是否重载全部版本
  1004. '检查Versions文件夹
  1005. If Not Directory.Exists(PATH_MC & "versions\") Then
  1006. VersionsList = New Dictionary(Of VersionSwapState, ArrayList) From {{VersionSwapState.UNKNOWN, New ArrayList}, {VersionSwapState.NORMAL, New ArrayList}, {VersionSwapState.SWAP, New ArrayList}, {VersionSwapState.OLD, New ArrayList}, {VersionSwapState.WRONG, New ArrayList}}
  1007. GoTo LoadEnd
  1008. End If
  1009. '遍历文件夹
  1010. Dim FolderList As New ArrayList
  1011. For Each Folder As DirectoryInfo In (New DirectoryInfo(PATH_MC & "versions")).GetDirectories
  1012. FolderList.Add(Folder.Name)
  1013. Next
  1014. '对比文件夹列表
  1015. Dim FolderListCheck As String = (MC_VERSION_CODE & "#" & Join(FolderList.ToArray, "#")).Replace(vbCrLf, "\n").Replace(":", "..").Replace("LastCheckedFolder", "LCF")
  1016. If Not ReadIni(PATH_MC & "PCL.ini", "LastCheckedFolder") = FolderListCheck Then
  1017. '文件夹列表不符
  1018. log("[Pool] 文件夹列表变更,重载所有版本")
  1019. ReloadAll = True
  1020. WriteIni(PATH_MC & "PCL.ini", "LastCheckedFolder", FolderListCheck)
  1021. End If
  1022. Reload:
  1023. VersionsList = New Dictionary(Of VersionSwapState, ArrayList) From {{VersionSwapState.UNKNOWN, New ArrayList}, {VersionSwapState.NORMAL, New ArrayList}, {VersionSwapState.SWAP, New ArrayList}, {VersionSwapState.OLD, New ArrayList}, {VersionSwapState.WRONG, New ArrayList}}
  1024. '遍历每个版本
  1025. For Each VersionName As String In FolderList
  1026. If Not CheckDirectoryPermission(PATH_MC & "versions\" & VersionName & "\") Then GoTo NextFolder
  1027. Dim Version As New MCVersion(VersionName)
  1028. Directory.CreateDirectory(Version.Path & "\PCL")
  1029. If ReadIni(Version.Path & "\PCL\Version.ini", "VersionListCode", "0") = MC_VERSION_CODE And Not ReloadAll Then
  1030. '存在有效的PCL配置文件,读取配置文件
  1031. Version.LoadedByFile = True
  1032. With Version
  1033. .SwapType = ReadIni(Version.Path & "\PCL\Version.ini", "SwapType")
  1034. .Version = ReadIni(Version.Path & "\PCL\Version.ini", "Version")
  1035. .ReleaseTime = ReadIni(Version.Path & "\PCL\Version.ini", "ReleaseTime")
  1036. .Assets = ReadIni(Version.Path & "\PCL\Version.ini", "Assets")
  1037. .MainVersionCode = ReadIni(Version.Path & "\PCL\Version.ini", "MainVersionCode")
  1038. .Type = ReadIni(Version.Path & "\PCL\Version.ini", "Type")
  1039. .Logo = ReadIni(Version.Path & "\PCL\Version.ini", "Logo")
  1040. .Description = ReadIni(Version.Path & "\PCL\Version.ini", "Description")
  1041. .VersionCheckResult = ReadIni(Version.Path & "\PCL\Version.ini", "VersionCheckResult")
  1042. .InheritVersion = ReadIni(Version.Path & "\PCL\Version.ini", "InheritVersion")
  1043. End With
  1044. '重新检测
  1045. Dim OldResult As VersionCheckState = Version.VersionCheckResult
  1046. CheckMCVersion(Version, Version.VersionCheckResult = VersionCheckState.INHERITS_EXCEPTION)
  1047. If Not Version.VersionCheckResult = OldResult Then
  1048. ReloadAll = True
  1049. GoTo Reload
  1050. End If
  1051. '图片的重新检测
  1052. If Not Version.Logo.StartsWith(PATH_IMAGE) Then
  1053. If Not File.Exists(Version.Logo) Then GoTo NotLoadFile
  1054. End If
  1055. Else
  1056. NotLoadFile:
  1057. '不存在PCL配置文件,读取版本信息
  1058. Version.LoadedByFile = False
  1059. CheckMCVersion(Version, True)
  1060. '版本存在错误
  1061. If Not Version.VersionCheckResult = VersionCheckState.NO_PROBLEM Then
  1062. '错误的版本
  1063. Version.SwapType = VersionSwapState.WRONG
  1064. GoTo NextVersion
  1065. End If
  1066. '尝试从继承版本处获取版本号
  1067. If Not Version.InheritVersion = "" Then
  1068. Version.Version = Version.InheritVersion
  1069. GoTo VersionSearchEnd
  1070. End If
  1071. '从json获取版本失败,试图从文件夹名称获取版本号,如果失败则标记“未知”
  1072. Dim CharCheck As ArrayList = RegexSearch(Version.Name, "1\.1?[0-9]{1}(\.[1-9]{1}([0-9]{1})?)?(-pre[1-9]?)?|1[2-9]{1}w[0-9]{1,2}[a-z]{1}")
  1073. If CharCheck.Count > 0 Then
  1074. Version.Version = CharCheck(0)
  1075. Else
  1076. Version.Version = "未知"
  1077. End If
  1078. VersionSearchEnd:
  1079. '获取发布时间
  1080. If Version.JsonText.Contains("releaseTime") Then
  1081. Version.ReleaseTime = RegexSearch(Version.JsonText.Replace(" ", ""), "(?<=releaseTime"":"")([^T]+)([^\+\-]+)")(0)
  1082. Else
  1083. Version.ReleaseTime = ""
  1084. End If
  1085. '设置主版本号
  1086. Dim MainVersion As ArrayList = RegexSearch(Version.Version, "1.[0-9]+")
  1087. Version.MainVersionCode = Math.Min(20, If(MainVersion.Count = 1, Int(MainVersion(0).Replace("1.", "")), 0))
  1088. '获取版本种类
  1089. Version.Type = MCVersionType.RELEASE
  1090. If Version.InheritVersion = "" Then
  1091. '无继承版本的
  1092. If Version.Version = "未知" Then Version.Type = MCVersionType.UNKNOWN
  1093. If Version.Version.ToLower.Contains("w") Or Version.Version.ToLower.Contains("pre") Or Version.JsonText.Replace(" ", "").Contains("""type"":""snapshot""") Then Version.Type = MCVersionType.SNAPSHOT
  1094. If Len(Version.ReleaseTime) > 6 Then If Val(Mid(Version.ReleaseTime, 3, 2)) < 14 Then Version.Type = MCVersionType.OLD '未知版本可能显示为1970年,故取后两位数
  1095. If If(IsNothing(Version.Json("type")), False, Version.Json("type") = "fool") Then Version.Type = MCVersionType.FOOL
  1096. If Version.JsonText.Contains("minecraftforge:minecraftforge") Then Version.Type = MCVersionType.FORGE
  1097. Else
  1098. '有继承版本的
  1099. Version.Type = If(Version.JsonText.Contains("Forge"), MCVersionType.FORGE, MCVersionType.OPTIFINE)
  1100. End If
  1101. '检测自定义种类信息
  1102. Version.SwapType = Val(ReadIni(Version.Path & "PCL\Setup.ini", "CustomType", "255"))
  1103. If Version.SwapType = VersionSwapState.UNKNOWN Then 'UNKNOWN为255
  1104. Select Case Version.Type
  1105. Case MCVersionType.SNAPSHOT, MCVersionType.RELEASE, MCVersionType.OPTIFINE
  1106. '需要再次确认是否应该折叠,不加处理
  1107. Case MCVersionType.OLD
  1108. '老版本,直接归类
  1109. Version.SwapType = VersionSwapState.OLD
  1110. Case MCVersionType.FOOL
  1111. '愚人节版本,直接折叠
  1112. Version.SwapType = VersionSwapState.SWAP
  1113. Case Else
  1114. '未知版本、Forge、不折叠版本,直接列入列表
  1115. Version.SwapType = VersionSwapState.NORMAL
  1116. End Select
  1117. End If
  1118. NextVersion:
  1119. '设置图标
  1120. If File.Exists(Version.Path & "PCL\Icon.png") Then
  1121. Try
  1122. Dim LogoTryLoad = New MyBitmap(Version.Path & "PCL\Icon.png")
  1123. Version.Logo = Version.Path & "PCL\Icon.png"
  1124. Catch ex As Exception
  1125. File.Delete(Version.Path & "PCL\Icon.png") '加载失败就删了图片,因为下一次还是会失败的……
  1126. GoTo CommonPicture
  1127. End Try
  1128. Else
  1129. CommonPicture:
  1130. Select Case Version.Type
  1131. Case MCVersionType.FORGE
  1132. Version.Logo = PATH_IMAGE & "Block-Anvil.png"
  1133. Case MCVersionType.OLD
  1134. Version.Logo = PATH_IMAGE & "Block-CobbleStone.png"
  1135. Case MCVersionType.SNAPSHOT
  1136. Version.Logo = PATH_IMAGE & "Block-CommandBlock.png"
  1137. Case MCVersionType.FOOL
  1138. Version.Logo = PATH_IMAGE & "Block-Dirt.png"
  1139. Case Else 'OptiFine、原版、未知
  1140. If Version.SwapType = VersionSwapState.WRONG Then
  1141. Version.Logo = PATH_IMAGE & "Block-RedstoneBlock.png"
  1142. Else
  1143. Version.Logo = PATH_IMAGE & "Block-Grass.png"
  1144. End If
  1145. End Select
  1146. End If
  1147. '设置描述文本
  1148. If Version.SwapType = VersionSwapState.WRONG Then
  1149. '错误描述文本
  1150. Select Case Version.VersionCheckResult
  1151. Case VersionCheckState.EMPTY_FOLDER
  1152. Version.Description = "空文件夹"
  1153. Case VersionCheckState.INHERITS_EXCEPTION
  1154. Version.Description = "依赖版本出错:" & Version.InheritVersion
  1155. Case VersionCheckState.INHERITS_NOT_EXIST
  1156. Version.Description = "依赖版本丢失:" & Version.InheritVersion
  1157. Case VersionCheckState.JAR_NOT_EXIST
  1158. Version.Description = "Jar 文件缺失"
  1159. Case VersionCheckState.JSON_CANT_READ
  1160. Version.Description = "Json 读取失败"
  1161. Case VersionCheckState.JSON_NOT_EXIST
  1162. Version.Description = "Json 文件缺失"
  1163. Case Else
  1164. Version.Description = "未知问题"
  1165. End Select
  1166. Else
  1167. '加载自定义文本
  1168. Version.Description = ReadIni(Version.Path & "PCL\Setup.ini", "Description")
  1169. If Version.Description = "" Then
  1170. '程序输出文本
  1171. Dim Description As String = If(Version.Type = MCVersionType.OPTIFINE, "OptiFine ", If(Version.Type = MCVersionType.FORGE, "Forge ", "")) & Version.Version
  1172. If Not Version.Name = Description And Not Description = "未知" Then Version.Description = Description
  1173. End If
  1174. End If
  1175. End If
  1176. VersionsList(Version.SwapType).Add(Version)
  1177. NextFolder:
  1178. Next
  1179. '判断是否需要重载列表次序
  1180. If VersionsList(VersionSwapState.UNKNOWN).Count = 0 Then GoTo LoadEnd
  1181. '计算最新的版本
  1182. Dim LargestTimeVer As New MCVersion("") '最新的版本
  1183. Dim LargestTime As ULong = 0 '最新的版本的时间
  1184. Dim CurrentTime As ULong '当前的版本的时间
  1185. Dim NewVersion As New Dictionary(Of String, MCVersion) '存储版本列表,键为“MainVersionCode-Type”
  1186. For Each ver As MCVersion In VersionsList(VersionSwapState.UNKNOWN)
  1187. CurrentTime = Val(ver.ReleaseTime.Replace("-", "").Replace(":", "").Replace("T", ""))
  1188. '取最大时间
  1189. If CurrentTime > LargestTime Then
  1190. LargestTime = CurrentTime
  1191. LargestTimeVer = ver
  1192. End If
  1193. 'OptiFine与正式版判断
  1194. If Not ver.Type = MCVersionType.SNAPSHOT Then
  1195. Dim CurrentVersion As New MCVersion("")
  1196. If NewVersion.TryGetValue(ver.MainVersionCode & "-" & ver.Type, CurrentVersion) Then
  1197. If CurrentTime > Val(CurrentVersion.ReleaseTime.Replace("-", "").Replace(":", "").Replace("T", "")) Then
  1198. NewVersion(ver.MainVersionCode & "-" & ver.Type) = ver
  1199. End If
  1200. Else
  1201. NewVersion.Add(ver.MainVersionCode & "-" & ver.Type, ver)
  1202. End If
  1203. End If
  1204. Next
  1205. '如果最新的版本为快照,则添加入列表
  1206. If LargestTimeVer.Type = MCVersionType.SNAPSHOT Then LargestTimeVer.SwapType = VersionSwapState.NORMAL
  1207. '准备检查后的主版本列表
  1208. Dim MainCodeList As New ArrayList '主版本列表
  1209. For Each Key As String In NewVersion.Keys
  1210. If Not MainCodeList.Contains(Integer.Parse(Key.Split("-")(0))) Then MainCodeList.Add(Integer.Parse(Key.Split("-")(0)))
  1211. Next
  1212. '把各个OptiFine和原版加入列表
  1213. Dim WillAdd As New ArrayList
  1214. For Each MainCode As Integer In MainCodeList
  1215. If NewVersion.ContainsKey(MainCode & "-" & MCVersionType.OPTIFINE) Then
  1216. '存在OptiFine版本
  1217. WillAdd.Add(NewVersion(MainCode & "-" & MCVersionType.OPTIFINE))
  1218. If NewVersion.ContainsKey(MainCode & "-" & MCVersionType.RELEASE) Then
  1219. '如果原版比OptiFine版更新也显示原版
  1220. If Val(NewVersion(MainCode & "-" & MCVersionType.RELEASE).ReleaseTime.Replace("-", "").Replace(":", "").Replace("T", "")) > Val(NewVersion(MainCode & "-" & MCVersionType.OPTIFINE).ReleaseTime.Replace("-", "").Replace(":", "").Replace("T", "")) Then
  1221. WillAdd.Add(NewVersion(MainCode & "-" & MCVersionType.RELEASE))
  1222. End If
  1223. End If
  1224. Else
  1225. '不存在OptiFine版本,检查原版版本
  1226. If NewVersion.ContainsKey(MainCode & "-" & MCVersionType.RELEASE) Then WillAdd.Add(NewVersion(MainCode & "-" & MCVersionType.RELEASE))
  1227. End If
  1228. Next
  1229. '列表处理
  1230. For Each Ver As MCVersion In WillAdd
  1231. Ver.SwapType = VersionSwapState.NORMAL
  1232. Next
  1233. For Each Ver As MCVersion In VersionsList(VersionSwapState.UNKNOWN)
  1234. If Ver.SwapType = VersionSwapState.UNKNOWN Then Ver.SwapType = VersionSwapState.SWAP
  1235. VersionsList(Ver.SwapType).Add(Ver)
  1236. Next
  1237. LoadEnd:
  1238. VersionsList.Remove(VersionSwapState.UNKNOWN)
  1239. '根据设置合并折叠与老版本
  1240. If ReadIni("setup", "HomeVersionSwap", "True") = "False" Then
  1241. VersionsList(VersionSwapState.NORMAL).AddRange(VersionsList(VersionSwapState.SWAP))
  1242. VersionsList(VersionSwapState.SWAP).Clear()
  1243. End If
  1244. If ReadIni("setup", "HomeVersionOld", "True") = "False" Then
  1245. VersionsList(VersionSwapState.NORMAL).AddRange(VersionsList(VersionSwapState.OLD))
  1246. VersionsList(VersionSwapState.OLD).Clear()
  1247. End If
  1248. '保存文件 & 列表排序
  1249. For Each List As ArrayList In VersionsList.Values
  1250. '排序
  1251. Dim Sorter As MCVersion() = ArrayConventer(Of MCVersion, ArrayList)(List)
  1252. Array.Sort(Sorter)
  1253. List.Clear()
  1254. For Each Item In Sorter
  1255. If Not IsNothing(Item) Then List.Add(Item)
  1256. Next
  1257. '写入文件
  1258. For Each Version As MCVersion In List
  1259. If Version.LoadedByFile = False Then
  1260. '写入PCL配置文件
  1261. Using iniWriter As New StreamWriter(Version.Path & "PCL\Version.ini", False, New UTF8Encoding(False))
  1262. iniWriter.WriteLine("VersionListCode:" & MC_VERSION_CODE)
  1263. iniWriter.WriteLine("SwapType:" & Version.SwapType)
  1264. iniWriter.WriteLine("Version:" & Version.Version)
  1265. iniWriter.WriteLine("ReleaseTime:" & Version.ReleaseTime)
  1266. iniWriter.WriteLine("MainVersionCode:" & Version.MainVersionCode)
  1267. iniWriter.WriteLine("Type:" & Version.Type)
  1268. iniWriter.WriteLine("Logo:" & Version.Logo)
  1269. iniWriter.WriteLine("Description:" & Version.Description)
  1270. iniWriter.WriteLine("VersionCheckResult:" & Version.VersionCheckResult)
  1271. iniWriter.WriteLine("InheritVersion:" & Version.InheritVersion)
  1272. iniWriter.Flush()
  1273. End Using
  1274. End If
  1275. Next
  1276. Next
  1277. log("[Pool] 预加载版本列表结束")
  1278. Catch ex As Exception
  1279. ExShow(ex, "加载版本列表失败", ErrorLevel.MsgboxAndFeedback)
  1280. '清空列表
  1281. VersionsList = New Dictionary(Of VersionSwapState, ArrayList)
  1282. Finally
  1283. frmHomeRight.Dispatcher.Invoke(Sub() frmHomeRight.LoadVersionList())
  1284. End Try
  1285. End Sub
  1286. ''' <summary>
  1287. ''' 加载线程:刷新背景图片和顶部图片。
  1288. ''' </summary>
  1289. ''' <remarks></remarks>
  1290. Public Sub PoolLoadPictures()
  1291. Try
  1292. If Not ReadIni("setup", "UiBackgroundURL", "") = "" Then
  1293. log("[Pool] 刷新背景图片开始")
  1294. DownloadFile(ReadIni("setup", "UiBackgroundURL", ""), PATH & "PCL\back.png" & DOWNLOADING_END)
  1295. File.Delete(PATH & "PCL\back.png")
  1296. FileSystem.Rename(PATH & "PCL\back.png" & DOWNLOADING_END, PATH & "PCL\back.png")
  1297. log("[Pool] 刷新背景图片结束")
  1298. End If
  1299. Catch ex As Exception
  1300. ExShow(ex, "刷新背景图片失败", ErrorLevel.AllUsers)
  1301. End Try
  1302. Try
  1303. If Not ReadIni("setup", "UiBarURL", "") = "" Then
  1304. log("[Pool] 刷新顶栏图片开始")
  1305. DownloadFile(ReadIni("setup", "UiBarURL", ""), PATH & "PCL\top.png" & DOWNLOADING_END)
  1306. File.Delete(PATH & "PCL\top.png")
  1307. FileSystem.Rename(PATH & "PCL\top.png" & DOWNLOADING_END, PATH & "PCL\top.png")
  1308. log("[Pool] 刷新顶栏图片结束")
  1309. End If
  1310. Catch ex As Exception
  1311. ExShow(ex, "刷新顶栏图片失败", ErrorLevel.AllUsers)
  1312. End Try
  1313. frmMain.Dispatcher.Invoke(New RefreshThemeInvoke(AddressOf RefreshTheme))
  1314. End Sub
  1315. Private PoolPushCount As Integer = 0
  1316. ''' <summary>
  1317. ''' 加载线程:首页。
  1318. ''' </summary>
  1319. ''' <remarks></remarks>
  1320. Public Class PushSource
  1321. Public Name As String
  1322. Public URL As String
  1323. Public Introduce As String
  1324. Public IsEnabled As String
  1325. Public LocalPath As String
  1326. End Class
  1327. Public Sub PoolPush()
  1328. If MODE_OFFLINE Then frmStart.IsPushLoading = False : Exit Sub
  1329. '加载特殊处理的第三方推荐
  1330. If ReadIni("setup", "HomeMCBBSPush", "True") = "True" Then Dim th As New Thread(AddressOf PoolMainMCBBS) : th.Priority = ThreadPriority.BelowNormal : th.Start() : PoolPushCount = PoolPushCount + 1
  1331. If ReadIni("setup", "HomeTbPush", "True") = "True" Then Dim th As New Thread(AddressOf PoolMainTb) : th.Priority = ThreadPriority.BelowNormal : th.Start() : PoolPushCount = PoolPushCount + 1
  1332. If ReadIni("setup", "HomeMojangPush", "True") = "True" Then Dim th As New Thread(AddressOf PoolMainMojang) : th.Priority = ThreadPriority.BelowNormal : th.Start() : PoolPushCount = PoolPushCount + 1
  1333. If ReadIni("setup", "HomeForumPush", "False") = "True" Then Dim th As New Thread(AddressOf PoolMainForum) : th.Priority = ThreadPriority.BelowNormal : th.Start() : PoolPushCount = PoolPushCount + 1
  1334. '加载默认推荐
  1335. Dim AllLocals As New ArrayList
  1336. If ReadIni("setup", "HomePCLPush", "True") = "True" Then AllLocals.Add(New PushSource With {.Name = "PCL 推荐", .URL = TX_SREVER_1 & "push.ini", .IsEnabled = True, .Introduce = "PCL 官方的优质内容推荐(不含广告请放心食用)。"})
  1337. '加载每个推荐
  1338. Dim Count As Integer = 0
  1339. For Each Push As PushSource In AllLocals
  1340. If Push.IsEnabled Then
  1341. PoolPushCount = PoolPushCount + 1
  1342. Dim Source As PushSource = Push
  1343. Dim thurl As New Thread(Sub() PoolMainPushURL(Source))
  1344. thurl.Start()
  1345. Count = Count + 1
  1346. End If
  1347. Next
  1348. If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1349. log("[Pool-HomeLeft] 订阅信息加载完成")
  1350. End Sub
  1351. #Region "推荐源"
  1352. ''' <summary>
  1353. ''' 贴吧源。
  1354. ''' </summary>
  1355. ''' <remarks></remarks>
  1356. Private Sub PoolMainTb()
  1357. log("[Pool-HomeLeft] 加载推荐源:Minecraft 吧精品")
  1358. If File.Exists(PATH & "PCL\cache\source\CA28E736032912D2801529958AB8937EBB351E2338212FA49529\cache.ini") Then
  1359. '如果缓存存在,读取->(下载->处理)
  1360. PoolMainTbLoad()
  1361. PoolPushCount = PoolPushCount - 1
  1362. If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1363. Thread.Sleep(5000)
  1364. PoolMainTbDownload()
  1365. Else
  1366. '如果缓存不存在,(下载->处理)->读取
  1367. If PoolMainTbDownload() Then PoolMainTbLoad()
  1368. PoolPushCount = PoolPushCount - 1
  1369. If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1370. End If
  1371. End Sub
  1372. Private Function PoolMainTbDownload() As Boolean
  1373. '————————————
  1374. '下载
  1375. '————————————
  1376. Dim SourceCode As String
  1377. Try
  1378. SourceCode = GetWebsiteCode("https://tieba.baidu.com/f?kw=minecraft&ie=utf-8&tab=good", New UTF8Encoding(False))
  1379. If SourceCode.Length < 100000 Then Throw New Exception("获取的代码长度不足:" & SourceCode)
  1380. Catch ex As Exception
  1381. ExShow(ex, "下载推荐源失败(Minecraft 吧精品)")
  1382. Return False
  1383. End Try
  1384. '————————————
  1385. '处理推荐
  1386. '————————————
  1387. Dim AllImages As New ArrayList
  1388. Dim AllLinks As New ArrayList
  1389. Dim AllTexts As New ArrayList
  1390. Try
  1391. '预处理范围
  1392. SourceCode = Mid(SourceCode, SourceCode.IndexOf("""thread_list"""))
  1393. SourceCode = Mid(SourceCode, 1, SourceCode.IndexOf("thread_list_bottom"))
  1394. Dim Threads As ArrayList = RegexSearch(SourceCode, "col2_right[\w\W]+?author_name")
  1395. Dim i As Integer = 0
  1396. For Count As Integer = 0 To 5
  1397. '每个帖子
  1398. AllLinks.Add("https://tieba.baidu.com" & RegexSearch(Threads(i), "/p/[^""]+")(0))
  1399. Threads(i) = Threads(i).ToString.Substring(Threads(i).ToString.IndexOf("a href="))
  1400. AllTexts.Add(RegexSearch(Threads(i), "(?<=title="")[^""]+")(0))
  1401. Dim ImageTry = RegexSearch(Threads(i), "(?<=data-original="")[^""]+")
  1402. AllImages.Add(If(ImageTry.Count > 0, ImageTry(0), ""))
  1403. i = i + RandomInteger(1, 3)
  1404. If i > Threads.Count - 1 Then Exit For
  1405. Next
  1406. Catch ex As Exception
  1407. ExShow(ex, "预处理推荐源失败(Minecraft 吧精品)")
  1408. Return False
  1409. End Try
  1410. '————————————
  1411. '项目过滤
  1412. '————————————
  1413. Dim Sources As New ArrayList
  1414. Try
  1415. For i = 0 To AllTexts.Count - 1
  1416. '检测是否为其它启动器广告
  1417. If Not (AllTexts(i).Contains("启动器") Or AllTexts(i).Contains("吧") Or AllTexts(i).Contains("水楼") Or AllTexts(i).Contains("赛") Or AllTexts(i).Contains("招聘") Or AllTexts(i).Contains("联机") Or AllTexts(i).Contains("服务器") Or AllTexts(i).Contains("HMCL") Or AllTexts(i).Contains("Launcher") Or AllTexts(i).Contains("Baka")) Then
  1418. Sources.Add(New InfoBoxSource With {
  1419. .OnClickURL = AllLinks(i),
  1420. .Title = AllTexts(i),
  1421. .Source = "Minecraft 吧精品",
  1422. .PictureName = AllImages(i),
  1423. .Type = ""})
  1424. End If
  1425. Next
  1426. '————————————
  1427. '图片种类、纯文本处理
  1428. '————————————
  1429. For Each Source As InfoBoxSource In Sources
  1430. GetSourceType(Source)
  1431. Dim regex As New RegularExpressions.Regex("\[[0-9]{2,4}-[0-9]{1,2}-[0-9]{1,2}\]")
  1432. Source.Title = regex.Replace(Source.Title, "")
  1433. If RegexSearch(Source.Title, "【[^0]{2,4}】").Count > 0 Then
  1434. If Source.Title.StartsWith(RegexSearch(Source.Title, "【[^0]{2,4}】")(0)) Then Source.Title = Source.Title.Replace(RegexSearch(Source.Title, "【[^0]{2,4}】")(0), "")
  1435. ElseIf RegexSearch(Source.Title, "\[[^0]{2,4}\]").Count > 0 Then
  1436. If Source.Title.StartsWith(RegexSearch(Source.Title, "\[[^0]{2,4}\]")(0)) Then Source.Title = Source.Title.Replace(RegexSearch(Source.Title, "\[[^0]{2,4}\]")(0), "")
  1437. End If
  1438. Next
  1439. Catch ex As Exception
  1440. ExShow(ex, "处理推荐源失败(Minecraft 吧精品)")
  1441. Return False
  1442. End Try
  1443. '————————————
  1444. '输出
  1445. '————————————
  1446. Dim OutputIni As String = "Version:" & PUSH_VERSION_CODE & vbCrLf
  1447. For i = 1 To Sources.Count
  1448. Dim Source As InfoBoxSource = Sources(i - 1)
  1449. OutputIni = OutputIni & vbCrLf
  1450. OutputIni = OutputIni & "Picture" & i & ":" & Source.PictureName & vbCrLf
  1451. OutputIni = OutputIni & "Title" & i & ":" & Source.Title & vbCrLf
  1452. OutputIni = OutputIni & "Link" & i & ":" & Source.OnClickURL & vbCrLf
  1453. OutputIni = OutputIni & "Type" & i & ":" & Source.Type & vbCrLf
  1454. Next
  1455. WriteFile("PCL\cache\source\CA28E736032912D2801529958AB8937EBB351E2338212FA49529\cache.ini", OutputIni, isFullPath:=False)
  1456. Return True
  1457. End Function
  1458. Private Sub PoolMainTbLoad()
  1459. PoolMainPushURLLoad(New PushSource With {
  1460. .LocalPath = PATH & "PCL\cache\source\CA28E736032912D2801529958AB8937EBB351E2338212FA49529\cache.ini",
  1461. .Name = "Minecraft 吧精品"})
  1462. End Sub
  1463. ''' <summary>
  1464. ''' Mojang 源。
  1465. ''' </summary>
  1466. ''' <remarks></remarks>
  1467. Private Sub PoolMainMojang()
  1468. log("[Pool-HomeLeft] 加载推荐源:Mojang 官方")
  1469. If File.Exists(PATH & "PCL\cache\source\A407DF2F142912192C15239087B89C1BBB82\cache.ini") Then
  1470. PoolMainMojangLoad()
  1471. PoolPushCount = PoolPushCount - 1 : If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1472. Thread.Sleep(5000)
  1473. PoolMainMojangDownload()
  1474. Else
  1475. '如果缓存不存在,(下载->处理)->读取
  1476. If PoolMainMojangDownload() Then PoolMainMojangLoad()
  1477. PoolPushCount = PoolPushCount - 1 : If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1478. End If
  1479. End Sub
  1480. Private Function PoolMainMojangDownload() As Boolean
  1481. '————————————
  1482. '下载
  1483. '————————————
  1484. Dim SourceCode As String
  1485. Try
  1486. SourceCode = GetWebsiteCode("http://www.mcbbs.net/portal.php", New UTF8Encoding(False))
  1487. If SourceCode.Length < 10000 Then Throw New Exception("获取的代码长度不足:" & SourceCode)
  1488. Catch ex As Exception
  1489. ExShow(ex, "下载推荐源失败(Mojang)")
  1490. Return False
  1491. End Try
  1492. '————————————
  1493. '处理推荐
  1494. '————————————
  1495. Dim AllImages As New ArrayList
  1496. Dim AllLinks As New ArrayList
  1497. Dim AllTexts As New ArrayList
  1498. Dim AllTypes As New ArrayList
  1499. '————————————
  1500. '加载
  1501. '————————————
  1502. Try
  1503. '去头尾
  1504. SourceCode = Mid(SourceCode, SourceCode.IndexOf("portal_zb"))
  1505. SourceCode = Mid(SourceCode, 1, SourceCode.IndexOf("titletext"))
  1506. '获取文本
  1507. AllImages = RegexSearch(SourceCode, "(?<=<img src="")[^""]+")
  1508. AllLinks = RegexSearch(SourceCode, "(?<=a href="")[^""]+")
  1509. AllTexts = RegexSearch(SourceCode, "(?<=;"">)[^<]+")
  1510. For i = 0 To AllTexts.Count - 1
  1511. AllTypes.Add("")
  1512. Next
  1513. Catch ex As Exception
  1514. ExShow(ex, "处理推荐源失败(Mojang)")
  1515. AllImages.Clear()
  1516. AllLinks.Clear()
  1517. AllTexts.Clear()
  1518. AllTypes.Clear()
  1519. End Try
  1520. '————————————
  1521. 'URL 二次处理及项目过滤
  1522. '————————————
  1523. Dim Sources As New ArrayList
  1524. Try
  1525. For i = 0 To AllLinks.Count - 1
  1526. If RegexSearch(AllLinks(i), "[0-9]{5,7}").Count = 0 Then
  1527. AllLinks(i) = ""
  1528. Else
  1529. AllLinks(i) = RegexSearch(AllLinks(i), "[0-9]{5,7}")(0)
  1530. End If
  1531. Next
  1532. Dim NoDoubledArray As ArrayList = ArrayNoDouble(AllLinks.ToArray)
  1533. For Each NoDoubledURL As String In NoDoubledArray
  1534. Dim Index As Integer = AllLinks.IndexOf(NoDoubledURL)
  1535. If Not Index >= AllTexts.Count Then
  1536. '检测是否为其它启动器广告
  1537. If Not (AllTexts(Index).Contains("启动器") Or AllTexts(Index).Contains("赛") Or AllTexts(Index).Contains("招聘") Or AllTexts(Index).Contains("联机") Or AllTexts(Index).Contains("服务器") Or AllTexts(Index).Contains("HMCL") Or AllTexts(Index).Contains("Launcher") Or AllTexts(Index).Contains("Baka") Or NoDoubledURL = "") Then
  1538. Sources.Add(New InfoBoxSource With {.OnClickURL = "http://www.mcbbs.net/thread-" & NoDoubledURL & "-1-1.html", .Title = AllTexts(Index), .Source = "Mojang 官方", .PictureName = AllImages(Index), .Type = AllTypes(Index)})
  1539. End If
  1540. End If
  1541. Next
  1542. '————————————
  1543. '图片种类、纯文本处理
  1544. '————————————
  1545. For Each Source As InfoBoxSource In Sources
  1546. Dim Title2 = Source.Title
  1547. GetSourceType(Source)
  1548. Source.Title = Title2
  1549. Next
  1550. Catch ex As Exception
  1551. ExShow(ex, "处理推荐源失败(Mojang)")
  1552. Return False
  1553. End Try
  1554. '————————————
  1555. '输出
  1556. '————————————
  1557. Dim OutputIni As String = "Version:" & PUSH_VERSION_CODE & vbCrLf
  1558. Dim IsWeekly As Boolean = False '每周的只显示一个
  1559. Dim OutI As Integer = 1 '用于输出的 i
  1560. For i = 1 To Sources.Count
  1561. If Sources(i - 1).Title.Contains("周") Then
  1562. If IsWeekly Then
  1563. GoTo NextSource
  1564. Else
  1565. IsWeekly = True
  1566. End If
  1567. End If
  1568. Dim Source As InfoBoxSource = Sources(i - 1)
  1569. OutputIni = OutputIni & vbCrLf
  1570. OutputIni = OutputIni & "Picture" & OutI & ":" & Source.PictureName & vbCrLf
  1571. OutputIni = OutputIni & "Title" & OutI & ":" & Source.Title & vbCrLf
  1572. OutputIni = OutputIni & "Link" & OutI & ":" & Source.OnClickURL & vbCrLf
  1573. OutputIni = OutputIni & "Type" & OutI & ":" & Source.Type & vbCrLf
  1574. OutI = OutI + 1
  1575. NextSource:
  1576. Next
  1577. WriteFile("PCL\cache\source\A407DF2F142912192C15239087B89C1BBB82\cache.ini", OutputIni, isFullPath:=False)
  1578. Return True
  1579. End Function
  1580. Private Sub PoolMainMojangLoad()
  1581. PoolMainPushURLLoad(New PushSource With {
  1582. .LocalPath = PATH & "PCL\cache\source\A407DF2F142912192C15239087B89C1BBB82\cache.ini",
  1583. .Name = "Mojang 官方"})
  1584. End Sub
  1585. ''' <summary>
  1586. ''' Forum 源。
  1587. ''' </summary>
  1588. ''' <remarks></remarks>
  1589. Private Sub PoolMainForum()
  1590. log("[Pool-HomeLeft] 加载推荐源:Minecraft Forum")
  1591. If File.Exists(PATH & "PCL\cache\source\" & Left(SerAdd("Minecraft Forum"), 100) & "\cache.ini") Then
  1592. PoolMainForumLoad()
  1593. PoolPushCount = PoolPushCount - 1 : If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1594. Thread.Sleep(5000)
  1595. PoolMainForumDownload()
  1596. Else
  1597. '如果缓存不存在,(下载->处理)->读取
  1598. If PoolMainForumDownload() Then PoolMainForumLoad()
  1599. PoolPushCount = PoolPushCount - 1 : If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1600. End If
  1601. End Sub
  1602. Private Function PoolMainForumDownload() As Boolean
  1603. '————————————
  1604. '下载
  1605. '————————————
  1606. Dim SourceCode As String
  1607. Try
  1608. SourceCode = GetWebsiteCode("http://www.minecraftforum.net/", New UTF8Encoding(False))
  1609. If SourceCode.Length < 500 Then Throw New Exception("获取的代码长度不足:" & SourceCode)
  1610. Catch ex As Exception
  1611. ExShow(ex, "下载推荐源失败(Minecraft Forum)")
  1612. Return False
  1613. End Try
  1614. '————————————
  1615. '处理推荐
  1616. '————————————
  1617. Dim AllLinks As New ArrayList
  1618. Dim AllTexts As New ArrayList
  1619. Dim AllImages As New ArrayList
  1620. Try
  1621. Dim Threads As ArrayList = RegexSearch(SourceCode, "<article>[\w\W]+?</article>")
  1622. Dim i As Integer = 0
  1623. For Count As Integer = 0 To 2
  1624. '每条Article
  1625. AllLinks.Add(RegexSearch(Threads(i), "http://www.minecraftforum.net/[^""]+")(0))
  1626. AllTexts.Add(RegexSearch(Threads(i), "(?<=<a href[^>]+>)[^<]{5,100}")(0))
  1627. AllImages.Add(RegexSearch(Threads(i), "(?<=<img src="")[^""]+")(0))
  1628. i = i + RandomInteger(1, 2)
  1629. If i > Threads.Count - 1 Then Exit For
  1630. Next
  1631. Catch ex As Exception
  1632. ExShow(ex, "预处理推荐源失败(Minecraft Forum)")
  1633. Return False
  1634. End Try
  1635. '————————————
  1636. '项目过滤
  1637. '————————————
  1638. Dim Sources As New ArrayList
  1639. Try
  1640. For i = 0 To AllTexts.Count - 1
  1641. If AllTexts(i).ToString.StartsWith(" ") Then AllTexts(i) = Right(AllTexts(i), Len(AllTexts(i)) - 1)
  1642. Sources.Add(New InfoBoxSource With {
  1643. .OnClickURL = AllLinks(i),
  1644. .Title = AllTexts(i),
  1645. .Source = "Minecraft Forum",
  1646. .PictureName = AllImages(i),
  1647. .Type = ""})
  1648. GetSourceType(Sources(Sources.Count - 1))
  1649. Next
  1650. Catch ex As Exception
  1651. ExShow(ex, "处理推荐源失败(Minecraft Forum)")
  1652. Return False
  1653. End Try
  1654. '————————————
  1655. '输出
  1656. '————————————
  1657. Dim OutputIni As String = "Version:" & PUSH_VERSION_CODE & vbCrLf
  1658. For i = 1 To Sources.Count
  1659. Dim Source As InfoBoxSource = Sources(i - 1)
  1660. OutputIni = OutputIni & vbCrLf
  1661. OutputIni = OutputIni & "Picture" & i & ":" & Source.PictureName & vbCrLf
  1662. OutputIni = OutputIni & "Title" & i & ":" & Source.Title & vbCrLf
  1663. OutputIni = OutputIni & "Link" & i & ":" & Source.OnClickURL & vbCrLf
  1664. OutputIni = OutputIni & "Type" & i & ":" & Source.Type & vbCrLf
  1665. Next
  1666. WriteFile("PCL\cache\source\" & Left(SerAdd("Minecraft Forum"), 100) & "\cache.ini", OutputIni, isFullPath:=False)
  1667. Return True
  1668. End Function
  1669. Private Sub PoolMainForumLoad()
  1670. PoolMainPushURLLoad(New PushSource With {
  1671. .LocalPath = PATH & "PCL\cache\source\" & Left(SerAdd("Minecraft Forum"), 100) & "\cache.ini",
  1672. .Name = "Minecraft Forum"})
  1673. End Sub
  1674. ''' <summary>
  1675. ''' MCBBS 源。
  1676. ''' </summary>
  1677. ''' <remarks></remarks>
  1678. Private Sub PoolMainMCBBS()
  1679. log("[Pool-HomeLeft] 加载推荐源:我的世界中文论坛")
  1680. If File.Exists(PATH & "PCL\cache\source\C6378196067760DF918A0145291AB651\cache.ini") Then
  1681. PoolMainMCBBSLoad()
  1682. PoolPushCount = PoolPushCount - 1 : If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1683. Thread.Sleep(5000)
  1684. PoolMainMCBBSDownload()
  1685. Else
  1686. '如果缓存不存在,(下载->处理)->读取
  1687. If PoolMainMCBBSDownload() Then PoolMainMCBBSLoad()
  1688. PoolPushCount = PoolPushCount - 1 : If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1689. End If
  1690. End Sub
  1691. Private Function PoolMainMCBBSDownload() As Boolean
  1692. '————————————
  1693. '下载
  1694. '————————————
  1695. Dim SourceCode As String
  1696. Try
  1697. SourceCode = GetWebsiteCode("http://www.mcbbs.net/forum.php", New UTF8Encoding(False))
  1698. If SourceCode.Length < 10000 Then Throw New Exception("获取的代码长度不足:" & SourceCode)
  1699. Catch ex As Exception
  1700. ExShow(ex, "下载推荐源失败(我的世界中文论坛)")
  1701. Return False
  1702. End Try
  1703. '————————————
  1704. '处理推荐
  1705. '————————————
  1706. Dim AllImages As New ArrayList
  1707. Dim AllLinks As New ArrayList
  1708. Dim AllTexts As New ArrayList
  1709. Dim AllTypes As New ArrayList
  1710. '————————————
  1711. '首页图片推荐
  1712. '————————————
  1713. Try
  1714. SourceCode = Mid(SourceCode, SourceCode.IndexOf("var files = '")).Replace(" var files = '", "")
  1715. AllImages.AddRange(Mid(SourceCode, 1, SourceCode.IndexOf("';")).Split("|"))
  1716. SourceCode = Mid(SourceCode, SourceCode.IndexOf("var links = '")).Replace(" var links = '", "")
  1717. AllLinks.AddRange(Mid(SourceCode, 1, SourceCode.IndexOf("';")).Split("|"))
  1718. SourceCode = Mid(SourceCode, SourceCode.IndexOf("var texts = '")).Replace(" var texts = '", "")
  1719. AllTexts.AddRange(Mid(SourceCode, 1, SourceCode.IndexOf("';")).Split("|"))
  1720. For i = 0 To AllTexts.Count - 1
  1721. AllTypes.Add("")
  1722. Next
  1723. Catch ex As Exception
  1724. ExShow(ex, "处理推荐源失败(我的世界中文论坛/图片推荐)")
  1725. AllImages.Clear()
  1726. AllLinks.Clear()
  1727. AllTexts.Clear()
  1728. AllTypes.Clear()
  1729. End Try
  1730. '————————————
  1731. '新闻资讯与最新精华
  1732. '————————————
  1733. Try
  1734. '最新精华
  1735. SourceCode = Mid(SourceCode, SourceCode.IndexOf("div id=""kk_xshow_cont_3"""))
  1736. Dim TextGood As String = Mid(SourceCode, 1, SourceCode.IndexOf("div id=""kk_xshow_cont_4"""))
  1737. Dim GoodLinks As New ArrayList(RegexSearch(TextGood, "(?<=a href="")[^""]+[0-9]{4,7}[^""]+(?="")"))
  1738. Dim GoodTexts As New ArrayList(RegexSearch(TextGood, "(?<=标题: )[^\n]+"))
  1739. For i = 0 To Math.Min(GoodLinks.Count - 1, 6) Step 0
  1740. AllLinks.Add(GoodLinks(i))
  1741. AllTexts.Add(GoodTexts(i))
  1742. AllImages.Add("")
  1743. AllTypes.Add("文本推荐")
  1744. i = i + RandomInteger(1, 3)
  1745. Next
  1746. '新闻资讯
  1747. SourceCode = Mid(SourceCode, SourceCode.IndexOf("div id=""diy_right"))
  1748. Dim SourceString = RegexSearch(SourceCode, "(?<=a href="")[^""]*[0-9]{5,7}[^""]*"" title=""[^""""]+(?="")")(0)
  1749. '处理源字符串
  1750. AllLinks.Add(Mid(SourceString, 1, SourceString.IndexOf(""" title=""")))
  1751. AllTexts.Add(Mid(SourceString, 10 + SourceString.IndexOf(""" title=""")))
  1752. AllImages.Add("")
  1753. AllTypes.Add("新闻")
  1754. Catch ex As Exception
  1755. ExShow(ex, "处理推荐源失败(我的世界中文论坛/文本推荐)")
  1756. End Try
  1757. '————————————
  1758. 'URL 二次处理及项目过滤
  1759. '————————————
  1760. Dim Sources As New ArrayList
  1761. Try
  1762. For i = 0 To AllLinks.Count - 1
  1763. If RegexSearch(AllLinks(i), "[0-9]{5,7}").Count = 0 Then
  1764. AllLinks(i) = ""
  1765. Else
  1766. AllLinks(i) = RegexSearch(AllLinks(i), "[0-9]{5,7}")(0)
  1767. End If
  1768. Next
  1769. Dim NoDoubledArray As ArrayList = ArrayNoDouble(AllLinks.ToArray)
  1770. For Each NoDoubledURL As String In NoDoubledArray
  1771. Dim Index As Integer = AllLinks.IndexOf(NoDoubledURL)
  1772. If Not Index >= AllTexts.Count Then
  1773. '检测是否为其它启动器广告
  1774. If Not (AllTexts(Index).Contains("启动器") Or AllTexts(Index).Contains("赛") Or AllTexts(Index).Contains("招聘") Or AllTexts(Index).Contains("联机") Or AllTexts(Index).Contains("服务器") Or AllTexts(Index).Contains("HMCL") Or AllTexts(Index).Contains("Launcher") Or AllTexts(Index).Contains("Baka") Or NoDoubledURL = "") Then
  1775. Sources.Add(New InfoBoxSource With {.OnClickURL = "http://www.mcbbs.net/thread-" & NoDoubledURL & "-1-1.html", .Title = AllTexts(Index), .Source = "我的世界中文论坛", .PictureName = AllImages(Index), .Type = AllTypes(Index)})
  1776. End If
  1777. End If
  1778. Next
  1779. '————————————
  1780. '图片种类、纯文本处理
  1781. '————————————
  1782. For Each Source As InfoBoxSource In Sources
  1783. Dim Title2 = Source.Title
  1784. GetSourceType(Source)
  1785. Source.Title = Title2
  1786. Next
  1787. Catch ex As Exception
  1788. ExShow(ex, "处理推荐源失败(我的世界中文论坛)")
  1789. Return False
  1790. End Try
  1791. '————————————
  1792. '输出
  1793. '————————————
  1794. Dim OutputIni As String = "Version:" & PUSH_VERSION_CODE & vbCrLf
  1795. For i = 1 To Sources.Count
  1796. Dim Source As InfoBoxSource = Sources(i - 1)
  1797. OutputIni = OutputIni & vbCrLf
  1798. OutputIni = OutputIni & "Picture" & i & ":" & Source.PictureName & vbCrLf
  1799. OutputIni = OutputIni & "Title" & i & ":" & Source.Title & vbCrLf
  1800. OutputIni = OutputIni & "Link" & i & ":" & Source.OnClickURL & vbCrLf
  1801. OutputIni = OutputIni & "Type" & i & ":" & Source.Type & vbCrLf
  1802. Next
  1803. WriteFile("PCL\cache\source\C6378196067760DF918A0145291AB651\cache.ini", OutputIni, isFullPath:=False)
  1804. Return True
  1805. End Function
  1806. Private Sub PoolMainMCBBSLoad()
  1807. PoolMainPushURLLoad(New PushSource With {
  1808. .LocalPath = PATH & "PCL\cache\source\C6378196067760DF918A0145291AB651\cache.ini",
  1809. .Name = "我的世界中文论坛"})
  1810. Thread.Sleep(2000)
  1811. End Sub
  1812. Public IsHaveAd As Boolean = False
  1813. ''' <summary>
  1814. ''' ini 源。
  1815. ''' </summary>
  1816. ''' <remarks></remarks>
  1817. Private Sub PoolMainPushURL(ByVal Source As PushSource)
  1818. log("[Pool-HomeLeft] 加载推荐源:" & Source.Name)
  1819. Source.LocalPath = PATH & "PCL\cache\source\" & Left(SerAdd(Source.Name), 100) & "\cache.ini"
  1820. If File.Exists(Source.LocalPath) Then
  1821. '如果缓存存在,读取->下载
  1822. PoolMainPushURLLoad(Source)
  1823. PoolPushCount = PoolPushCount - 1 : If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1824. Thread.Sleep(5000)
  1825. PoolMainPushURLDownload(Source)
  1826. Else
  1827. '如果缓存不存在,(下载->处理)->读取
  1828. If PoolMainPushURLDownload(Source) Then PoolMainPushURLLoad(Source)
  1829. PoolPushCount = PoolPushCount - 1 : If PoolPushCount = 0 Then frmStart.IsPushLoading = False
  1830. End If
  1831. End Sub
  1832. Private Function PoolMainPushURLDownload(ByVal Source As PushSource) As Boolean
  1833. If DownloadFile(Source.URL, Source.LocalPath) Then
  1834. If Val(ReadIni(Source.LocalPath, "Version", "0")) < PUSH_VERSION_CODE Then
  1835. log("[Pool-HomeLeft] 推荐源版本过老(" & Source.Name & "):目前为 " & ReadIni(Source.LocalPath, "Version", "0") & ",要求为 " & PUSH_VERSION_CODE, True)
  1836. Return False
  1837. End If
  1838. Return True
  1839. Else
  1840. log("[Pool-HomeLeft] 下载推荐源失败:" & Source.Name, True)
  1841. Return False
  1842. End If
  1843. End Function
  1844. Private Sub PoolMainPushURLLoad(ByVal Source As PushSource)
  1845. '版本检查
  1846. If Val(ReadIni(Source.LocalPath, "Version", "0")) < PUSH_VERSION_CODE Then
  1847. log("[Pool-HomeLeft] 推荐源版本过老(" & Source.Name & "):目前为 " & ReadIni(Source.LocalPath, "Version", "0") & ",要求为 " & PUSH_VERSION_CODE, True)
  1848. Exit Sub
  1849. End If
  1850. '处理代码
  1851. Try
  1852. Dim CanLoadItem As New ArrayList
  1853. Dim ii As Integer = 1
  1854. Do Until ReadIni(Source.LocalPath, "Title" & ii) = ""
  1855. '过滤
  1856. Dim Context As String = ReadIni(Source.LocalPath, "Title" & ii)
  1857. If Context.Contains("Plain Craft Launcher") Or Context.Contains("PCL") Or Not (Context.Contains("启动器") Or Context.Contains("HMCL") Or Context.Contains("Launcher") Or Context.Contains("Baka") Or ReadIni(Source.LocalPath, "Link" & ii).Contains("twitter")) Then
  1858. Dim InfoSource As New InfoBoxSource With {
  1859. .OnClickURL = ReadIni(Source.LocalPath, "Link" & ii),
  1860. .PictureName = ReadIni(Source.LocalPath, "Picture" & ii),
  1861. .Title = Context,
  1862. .Source = Source.Name,
  1863. .Type = ReadIni(Source.LocalPath, "Type" & ii)}
  1864. '纯文本订阅只保留一半
  1865. If Not InfoSource.PictureName.Contains("://") Then
  1866. If ReadIni("setup", "HomeHide", "True") = "True" And Not RandomInteger(0, 1) = 1 Then GoTo NextItem
  1867. End If
  1868. frmHomeLeft.LoadingItem.Add(InfoSource)
  1869. InfoSource.Load()
  1870. End If
  1871. NextItem:
  1872. ii = ii + 1
  1873. Loop
  1874. Catch ex As Exception
  1875. log("[Pool-HomeLeft] 处理推荐源失败(" & Source.Name & "):" & GetStringFromException(ex, True), True)
  1876. End Try
  1877. End Sub
  1878. Private Sub GetSourceType(ByRef Source As InfoBoxSource)
  1879. If Source.Type = "新闻" Then
  1880. ElseIf Source.Title.Contains("教程") Or Source.Title.Contains("新手") Or Source.Title.Contains("技巧") Or Source.Title.ToLower.Contains("wiki") Or Source.Title.Contains("翻译") Then
  1881. Source.Type = "教程"
  1882. ElseIf Source.Title.Contains("编辑器") Or Source.Title.Contains("软件") Or Source.Title.Contains("工具") Or Source.Title.Contains("生成器") Then
  1883. Source.Type = "软件"
  1884. ElseIf Source.Title.Contains("联机") Or Source.Title.Contains("插件") Or Source.Title.Contains("服务端") Or Source.Title.Contains("开服") Or Source.Title.Contains("服务器") Then
  1885. Source.Type = "多人"
  1886. ElseIf Source.Title.Contains("皮肤") Then
  1887. Source.Type = "皮肤"
  1888. ElseIf Source.Title.ToLower.Contains("mod") Then
  1889. Source.Type = "Mod"
  1890. ElseIf Source.Title.Contains("解密") Or Source.Title.Contains("逃") Or Source.Title.Contains("跑酷") Or Source.Title.Contains("空岛") Or Source.Title.Contains("RPG") Or Source.Title.Contains("生存") Or Source.Title.Contains("小游戏") Or Source.Title.Contains("CB") Or Source.Title.Contains("红石") Or Source.Title.Contains("闯关") Or Source.Title.Contains("PVP") Or Source.Title.Contains("PVE") Or Source.Title.Contains("命令") Or Source.Title.Contains("战") Or Source.Title.Contains("冒险") Then
  1891. Source.Type = "地图"
  1892. ElseIf Source.Title.Contains("创作") Or Source.Title.Contains("小说") Or Source.Title.Contains("漫画") Or Source.Title.Contains("物语") Or Source.Title.Contains("插画") Or Source.Title.Contains("短篇") Or Source.Title.Contains("长篇") Then
  1893. Source.Type = "创作"
  1894. ElseIf Source.Title.Contains("材质") Or Source.Title.Contains("资源包") Then
  1895. Source.Type = "资源包"
  1896. ElseIf Source.Title.Contains("整合") Or Source.Title.Contains("懒人包") Then
  1897. Source.Type = "懒人包"
  1898. ElseIf Source.Title.Contains("阁") Or Source.Title.Contains("航母") Or Source.Title.Contains("港") Or Source.Title.Contains("宫") Or Source.Title.Contains("上古之石") Or Source.Title.Contains("楼") Or Source.Title.Contains("城") Or Source.Title.Contains("镇") Or Source.Title.Contains("殿") Or Source.Title.Contains("厅") Or Source.Title.Contains("桥") Or Source.Title.Contains("陵") Or Source.Title.Contains("园") Or Source.Title.Contains("宅") Or Source.Title.Contains("街") Or Source.Title.Contains("筑") Or Source.Title.Contains("山") Or Source.Title.Contains("景") Or Source.Title.ToLower.Contains("city") Then
  1899. Source.Type = "建筑"
  1900. ElseIf Source.Title.Contains("地图") Or Source.Title.Contains("作品") Then
  1901. Source.Type = "地图"
  1902. ElseIf Source.Source = "Minecraft Forum" Or Source.Title.Contains("发布") Or Source.Title.Contains("eleas") Then
  1903. Source.Type = "新闻"
  1904. Else
  1905. Source.Type = ""
  1906. End If
  1907. End Sub
  1908. #End Region
  1909. #End Region
  1910. #Region "自动安装"
  1911. ''' <summary>
  1912. ''' 自动安装文件或文件夹。
  1913. ''' </summary>
  1914. ''' <param name="Path">文件或文件夹完整路径。文件夹不以“\”结尾。</param>
  1915. ''' <remarks></remarks>
  1916. Public Sub AutoSetup(ByVal Path As String)
  1917. log("[System] 安装文件请求:" & Path)
  1918. Try
  1919. '基础检测
  1920. If Directory.Exists(Path) Then
  1921. '文件夹
  1922. Path = Path & "\"
  1923. Dim a = Path & GetFileNameFromPath(Mid(Path, 1, Len(Path) - 1)) & ".jar"
  1924. ReCheckDir:
  1925. If File.Exists(Path & "level.dat") And Directory.Exists(Path & "region") Then
  1926. '存档文件夹
  1927. Dim th As New Thread(AddressOf AutoSetupSaveFolder)
  1928. th.Start(Path)
  1929. ElseIf File.Exists(Path & "pack.mcmeta") And Directory.Exists(Path & "assets") Then
  1930. '资源包文件夹
  1931. Dim th As New Thread(AddressOf AutoSetupResFolder)
  1932. th.Start(Path)
  1933. ElseIf File.Exists(Path & GetFileNameFromPath(Mid(Path, 1, Len(Path) - 1)) & ".jar") And File.Exists(Path & GetFileNameFromPath(Mid(Path, 1, Len(Path) - 1)) & ".json") Then
  1934. '版本文件夹
  1935. Dim th As New Thread(AddressOf AutoSetupVersionFolder)
  1936. th.Start(Path)
  1937. Else
  1938. '进一层鉴别
  1939. Dim AllDir As String() = Directory.GetDirectories(Path)
  1940. If AllDir.Length = 1 Then
  1941. '发现进一层文件夹
  1942. Path = AllDir(0) & "\"
  1943. log("[System] 进一层的文件夹:" & Path)
  1944. GoTo ReCheckDir
  1945. Else
  1946. '没有进一层文件夹
  1947. ShowHint(New HintConverter("自动安装失败:不支持的文件夹", HintState.Warn))
  1948. Exit Sub
  1949. End If
  1950. End If
  1951. ElseIf File.Exists(Path) Then
  1952. '文件
  1953. '获取后缀
  1954. Dim SplitResult As String() = Path.Split(".")
  1955. Dim EndDot As String = If(SplitResult.Length > 1, SplitResult(SplitResult.Length - 1), "")
  1956. '判断后缀
  1957. If EndDot = "zip" Then
  1958. 'zip处理线程
  1959. Dim th As New Thread(Sub()
  1960. Try
  1961. Using zip As New ZipFile(Path, Encoding.Default)
  1962. Dim BasePath As String = "" '基础路径,用于一层嵌套的文件
  1963. ReCheckZip:
  1964. '检查是否为版本文件夹
  1965. Dim LastPath As String
  1966. If BasePath = "" Then
  1967. LastPath = GetFileNameFromPath(Path).Replace(".zip", "")
  1968. Else
  1969. LastPath = Mid(BasePath, 1, Len(BasePath) - 1).Split("/")(Mid(BasePath, 1, Len(BasePath) - 1).Split("/").Length - 1)
  1970. End If
  1971. log("[System] 末端文件夹名:" & LastPath)
  1972. '文件检查
  1973. If zip.ContainsEntry(BasePath & "level.dat") And zip.ContainsEntry(BasePath & "region/") Then
  1974. '存档zip
  1975. AutoSetupSaveZip(zip, BasePath, Path)
  1976. ElseIf zip.ContainsEntry(BasePath & "pack.mcmeta") And zip.ContainsEntry(BasePath & "assets/") Then
  1977. '资源包zip
  1978. If BasePath = "" Then
  1979. AutoSetupResZip(Path)
  1980. Else
  1981. ShowHint(New HintConverter("自动安装失败:资源包压缩包不支持内置文件夹", HintState.Warn))
  1982. Exit Sub
  1983. End If
  1984. ElseIf zip.ContainsEntry(BasePath & LastPath & ".jar") And zip.ContainsEntry(BasePath & LastPath & ".json") Then
  1985. '版本zip
  1986. AutoSetupVersionZip(zip, BasePath, Path)
  1987. Else
  1988. '进一层鉴别
  1989. Dim AllDir As New ArrayList
  1990. For Each Entry As String In zip.EntryFileNames
  1991. If Entry.IndexOf("/") = Len(Entry) - 1 Then AllDir.Add(Entry)
  1992. Next
  1993. If AllDir.Count = 1 Then
  1994. BasePath = AllDir(0)
  1995. log("[System] 进一层的压缩文件路径:" & BasePath)
  1996. GoTo ReCheckZip
  1997. Else
  1998. ShowHint(New HintConverter("自动安装失败:不支持的文件", HintState.Warn))
  1999. Exit Sub
  2000. End If
  2001. End If
  2002. End Using
  2003. Catch ex As Exception
  2004. ShowHint(New HintConverter("自动安装失败:" & GetStringFromException(ex), HintState.Warn))
  2005. End Try
  2006. End Sub)
  2007. th.Start()
  2008. ElseIf EndDot = "json" Or EndDot = "jar" Then
  2009. '版本文件
  2010. AutoSetupVersionFile(Path, EndDot)
  2011. ElseIf EndDot = "rar" Or EndDot = "7z" Then
  2012. ShowHint(New HintConverter("自动安装失败:PCL暂时只支持.zip文件", HintState.Warn))
  2013. Exit Sub
  2014. Else
  2015. ShowHint(New HintConverter("自动安装失败:未知的文件后缀", HintState.Warn))
  2016. Exit Sub
  2017. End If
  2018. Else
  2019. ShowHint(New HintConverter("自动安装失败:它既不是文件也不是文件夹", HintState.Warn))
  2020. Exit Sub
  2021. End If
  2022. Catch ex As Exception
  2023. ExShow(ex, "自动安装失败", ErrorLevel.AllUsers)
  2024. End Try
  2025. End Sub
  2026. ''' <summary>
  2027. ''' 自动安装存档文件夹。需要异步调用。
  2028. ''' </summary>
  2029. ''' <param name="DirPath">文件夹路径,以“\”结尾。</param>
  2030. ''' <remarks></remarks>
  2031. Public Sub AutoSetupSaveFolder(ByVal DirPath As String)
  2032. Try
  2033. log("[System] 存档文件夹:" & DirPath)
  2034. Dim SaveName As String = GetFileNameFromPath(Left(DirPath, Len(DirPath) - 1))
  2035. Dim TargetPath As String = PATH_MC & "saves\" & SaveName & "\"
  2036. Directory.CreateDirectory(PATH_MC & "saves\")
  2037. If TargetPath = DirPath Then Exit Sub '路径相同
  2038. '已存在检测
  2039. Recheck:
  2040. If Directory.Exists(TargetPath) Then
  2041. Select Case AutoSetupCheck("存档 " & SaveName & " 已经存在。" & vbCrLf & "位置:" & TargetPath, True)
  2042. Case 1
  2043. '替换
  2044. ShowHint("正在删除原存档:" & SaveName)
  2045. Directory.Delete(TargetPath, True)
  2046. Case 2
  2047. '重命名
  2048. TargetPath = Left(TargetPath, Len(TargetPath) - 1) & "-\"
  2049. SaveName = SaveName & "-"
  2050. GoTo Recheck
  2051. Case 3
  2052. '取消
  2053. Exit Sub
  2054. End Select
  2055. End If
  2056. ShowHint("正在安装存档:" & SaveName)
  2057. Directory.CreateDirectory(TargetPath)
  2058. My.Computer.FileSystem.CopyDirectory(DirPath, TargetPath)
  2059. ShowHint(New HintConverter("安装存档成功:" & SaveName, HintState.Finish))
  2060. Catch ex As Exception
  2061. ExShow(ex, "自动安装失败", ErrorLevel.AllUsers)
  2062. End Try
  2063. End Sub
  2064. ''' <summary>
  2065. ''' 自动安装资源包文件夹。需要异步调用。
  2066. ''' </summary>
  2067. ''' <param name="DirPath">文件夹路径,以“\”结尾。</param>
  2068. ''' <remarks></remarks>
  2069. Public Sub AutoSetupResFolder(ByVal DirPath As String)
  2070. Try
  2071. log("[System] 资源包文件夹:" & DirPath)
  2072. Dim SaveName As String = GetFileNameFromPath(Left(DirPath, Len(DirPath) - 1))
  2073. Dim TargetPath As String = PATH_MC & "resourcepacks\" & SaveName & "\"
  2074. Directory.CreateDirectory(PATH_MC & "resourcepacks\")
  2075. If TargetPath = DirPath Then Exit Sub '路径相同
  2076. '已存在检测
  2077. Recheck:
  2078. If Directory.Exists(TargetPath) Then
  2079. Select Case AutoSetupCheck("资源包 " & SaveName & " 已经存在。" & vbCrLf & "位置:" & TargetPath)
  2080. Case 1
  2081. '替换
  2082. ShowHint("正在删除原资源包:" & SaveName)
  2083. Directory.Delete(TargetPath, True)
  2084. Case 2
  2085. '取消
  2086. Exit Sub
  2087. End Select
  2088. End If
  2089. ShowHint("正在安装资源包:" & SaveName)
  2090. Directory.CreateDirectory(TargetPath)
  2091. My.Computer.FileSystem.CopyDirectory(DirPath, TargetPath)
  2092. ShowHint(New HintConverter("安装资源包成功:" & SaveName, HintState.Finish))
  2093. Catch ex As Exception
  2094. ExShow(ex, "自动安装失败", ErrorLevel.AllUsers)
  2095. End Try
  2096. End Sub
  2097. ''' <summary>
  2098. ''' 自动安装版本文件夹。需要异步调用。
  2099. ''' </summary>
  2100. ''' <param name="DirPath">文件夹路径,以“\”结尾。</param>
  2101. ''' <remarks></remarks>
  2102. Public Sub AutoSetupVersionFolder(ByVal DirPath As String)
  2103. Try
  2104. log("[System] 版本文件夹:" & DirPath)
  2105. Dim SaveName As String = GetFileNameFromPath(Left(DirPath, Len(DirPath) - 1))
  2106. Dim TargetPath As String = PATH_MC & "versions\" & SaveName & "\"
  2107. Directory.CreateDirectory(PATH_MC & "versions\")
  2108. If TargetPath = DirPath Then Exit Sub '路径相同
  2109. '已存在检测
  2110. Recheck:
  2111. If Directory.Exists(TargetPath) Then
  2112. Select Case AutoSetupCheck("版本 " & SaveName & " 已经存在。" & vbCrLf & "位置:" & TargetPath)
  2113. Case 1
  2114. '替换
  2115. ShowHint("正在删除原版本:" & SaveName)
  2116. Directory.Delete(TargetPath, True)
  2117. Case 2
  2118. '取消
  2119. Exit Sub
  2120. End Select
  2121. End If
  2122. ShowHint("正在安装版本:" & SaveName)
  2123. Directory.CreateDirectory(TargetPath)
  2124. My.Computer.FileSystem.CopyDirectory(DirPath, TargetPath)
  2125. ShowHint(New HintConverter("安装版本成功:" & SaveName, HintState.Finish))
  2126. Catch ex As Exception
  2127. ExShow(ex, "自动安装失败", ErrorLevel.AllUsers)
  2128. End Try
  2129. '强制重载版本列表
  2130. WriteIni(PATH_MC & "PCL.ini", "LastCheckedFolder", "")
  2131. Pool.Add(New Thread(AddressOf PoolVersionList))
  2132. End Sub
  2133. ''' <summary>
  2134. ''' 自动安装版本文件。需要异步调用。
  2135. ''' </summary>
  2136. ''' <param name="FilePath">文件路径。</param>
  2137. ''' <param name="EndDot">文件后缀。不包含小数点。</param>
  2138. ''' <remarks></remarks>
  2139. Public Sub AutoSetupVersionFile(ByVal FilePath As String, ByVal EndDot As String)
  2140. Try
  2141. log("[System] 版本文件:" & FilePath)
  2142. Dim SaveName As String = GetFileNameFromPath(FilePath).Replace("." & EndDot, "")
  2143. Dim TargetPath As String = PATH_MC & "versions\" & SaveName & "\" & SaveName & "." & EndDot
  2144. Directory.CreateDirectory(PATH_MC & "versions\")
  2145. If TargetPath = FilePath Then Exit Sub '路径相同
  2146. '已存在检测
  2147. Recheck:
  2148. If Directory.Exists(PATH_MC & "versions\" & SaveName & "\") Then
  2149. If File.Exists(TargetPath) Then
  2150. Select Case AutoSetupCheck("版本文件 " & SaveName & " 已经存在。" & vbCrLf & "位置:" & TargetPath, True)
  2151. Case 1
  2152. '替换
  2153. ShowHint("正在删除原版本文件:" & SaveName)
  2154. File.Delete(TargetPath)
  2155. Case 2
  2156. '重命名
  2157. SaveName = SaveName & "-"
  2158. TargetPath = PATH_MC & "versions\" & SaveName & "\" & SaveName & "." & EndDot
  2159. GoTo Recheck
  2160. Case 3
  2161. '取消
  2162. Exit Sub
  2163. End Select
  2164. End If
  2165. End If
  2166. ShowHint("正在安装版本文件:" & SaveName)
  2167. Directory.CreateDirectory(PATH_MC & "versions\" & SaveName & "\")
  2168. File.Copy(FilePath, TargetPath)
  2169. ShowHint(New HintConverter("安装版本文件成功:" & SaveName, HintState.Finish))
  2170. Catch ex As Exception
  2171. ExShow(ex, "自动安装失败", ErrorLevel.AllUsers)
  2172. End Try
  2173. '强制重载版本列表
  2174. WriteIni(PATH_MC & "PCL.ini", "LastCheckedFolder", "")
  2175. Pool.Add(New Thread(AddressOf PoolVersionList))
  2176. End Sub
  2177. ''' <summary>
  2178. ''' 自动安装存档zip压缩包。需要异步调用。
  2179. ''' </summary>
  2180. ''' <param name="Zip">ZipFile类型的已经打开的压缩文件对象。</param>
  2181. ''' <param name="BasePath">在压缩文件中的基础路径。</param>
  2182. ''' <remarks></remarks>
  2183. Public Sub AutoSetupSaveZip(ByVal Zip As ZipFile, ByVal BasePath As String, ByVal FilePath As String)
  2184. Try
  2185. log("[System] 存档zip" & If(BasePath = "", "", ":" & BasePath))
  2186. Dim SaveName As String = If(BasePath = "", GetFileNameFromPath(FilePath).Replace(".zip", ""), Left(BasePath, Len(BasePath) - 1))
  2187. Dim TargetPath As String = PATH_MC & "saves\" & SaveName & "\"
  2188. Directory.CreateDirectory(PATH_MC & "saves\")
  2189. '已存在检测
  2190. Dim Renamed As Boolean = False
  2191. Recheck:
  2192. If Directory.Exists(TargetPath) Then
  2193. Select Case AutoSetupCheck("存档 " & SaveName & " 已经存在。" & vbCrLf & "位置:" & TargetPath, True)
  2194. Case 1
  2195. '替换
  2196. ShowHint("正在删除原存档:" & SaveName)
  2197. Directory.Delete(TargetPath, True)
  2198. Case 2
  2199. '重命名
  2200. TargetPath = Left(TargetPath, Len(TargetPath) - 1) & "-\"
  2201. SaveName = SaveName & "-"
  2202. Renamed = True
  2203. GoTo Recheck
  2204. Case 3
  2205. '取消
  2206. Exit Sub
  2207. End Select
  2208. End If
  2209. ShowHint("正在安装存档:" & SaveName)
  2210. Directory.CreateDirectory(TargetPath)
  2211. If BasePath = "" Then
  2212. Zip.ExtractAll(TargetPath, ExtractExistingFileAction.OverwriteSilently)
  2213. Else
  2214. Zip.ExtractAll(PATH, ExtractExistingFileAction.OverwriteSilently)
  2215. My.Computer.FileSystem.CopyDirectory(PATH & Left(BasePath, Len(BasePath) - 1), TargetPath)
  2216. Directory.Delete(PATH & Left(BasePath, Len(BasePath) - 1), True)
  2217. End If
  2218. ShowHint(New HintConverter("安装存档成功:" & SaveName, HintState.Finish))
  2219. Catch ex As Exception
  2220. ExShow(ex, "自动安装失败", ErrorLevel.AllUsers)
  2221. End Try
  2222. End Sub
  2223. ''' <summary>
  2224. ''' 自动安装资源包zip压缩包。需要异步调用。
  2225. ''' </summary>
  2226. ''' <param name="FilePath">Zip文件路径。</param>
  2227. ''' <remarks></remarks>
  2228. Public Sub AutoSetupResZip(ByVal FilePath As String)
  2229. Try
  2230. log("[System] 资源包zip:" & FilePath)
  2231. Dim SaveName As String = GetFileNameFromPath(FilePath)
  2232. Dim TargetPath As String = PATH_MC & "resourcepacks\" & SaveName
  2233. Directory.CreateDirectory(PATH_MC & "resourcepacks\")
  2234. If TargetPath = FilePath Then Exit Sub '路径相同
  2235. '已存在检测
  2236. Recheck:
  2237. If File.Exists(TargetPath) Then
  2238. Select Case AutoSetupCheck("资源包 " & SaveName & " 已经存在。" & vbCrLf & "位置:" & TargetPath)
  2239. Case 1
  2240. '替换
  2241. ShowHint("正在删除原资源包:" & SaveName)
  2242. File.Delete(TargetPath)
  2243. Case 2
  2244. '取消
  2245. Exit Sub
  2246. End Select
  2247. End If
  2248. ShowHint("正在安装资源包:" & SaveName)
  2249. File.Copy(FilePath, TargetPath)
  2250. ShowHint(New HintConverter("安装资源包成功:" & SaveName, HintState.Finish))
  2251. Catch ex As Exception
  2252. ExShow(ex, "自动安装失败", ErrorLevel.AllUsers)
  2253. End Try
  2254. End Sub
  2255. ''' <summary>
  2256. ''' 自动安装版本zip压缩包。需要异步调用。
  2257. ''' </summary>
  2258. ''' <param name="Zip">ZipFile类型的已经打开的压缩文件对象。</param>
  2259. ''' <param name="BasePath">在压缩文件中的基础路径。</param>
  2260. ''' <remarks></remarks>
  2261. Public Sub AutoSetupVersionZip(ByVal Zip As ZipFile, ByVal BasePath As String, ByVal FilePath As String)
  2262. Try
  2263. log("[System] 版本zip" & If(BasePath = "", "", ":" & BasePath))
  2264. Dim VersionName As String = If(BasePath = "", GetFileNameFromPath(FilePath).Replace(".zip", ""), Left(BasePath, Len(BasePath) - 1))
  2265. Dim TargetPath As String = PATH_MC & "versions\" & VersionName & "\"
  2266. Directory.CreateDirectory(PATH_MC & "versions\")
  2267. '已存在检测
  2268. Dim Renamed As Boolean = False
  2269. Recheck:
  2270. If Directory.Exists(TargetPath) Then
  2271. Select Case AutoSetupCheck("版本 " & VersionName & " 已经存在。" & vbCrLf & "位置:" & TargetPath)
  2272. Case 1
  2273. '替换
  2274. ShowHint("正在删除原版本:" & VersionName)
  2275. Directory.Delete(TargetPath, True)
  2276. Case 2
  2277. '取消
  2278. Exit Sub
  2279. End Select
  2280. End If
  2281. ShowHint("正在安装版本:" & VersionName)
  2282. Directory.CreateDirectory(TargetPath)
  2283. If BasePath = "" Then
  2284. Zip.ExtractAll(TargetPath, ExtractExistingFileAction.OverwriteSilently)
  2285. Else
  2286. Zip.ExtractAll(PATH, ExtractExistingFileAction.OverwriteSilently)
  2287. My.Computer.FileSystem.CopyDirectory(PATH & Left(BasePath, Len(BasePath) - 1), TargetPath)
  2288. Directory.Delete(PATH & Left(BasePath, Len(BasePath) - 1), True)
  2289. End If
  2290. ShowHint(New HintConverter("安装版本成功:" & VersionName, HintState.Finish))
  2291. Catch ex As Exception
  2292. ExShow(ex, "自动安装失败", ErrorLevel.AllUsers)
  2293. End Try
  2294. '强制重载版本列表
  2295. WriteIni(PATH_MC & "PCL.ini", "LastCheckedFolder", "")
  2296. Pool.Add(New Thread(AddressOf PoolVersionList))
  2297. End Sub
  2298. ''' <summary>
  2299. ''' 弹出自动安装的确认消息。需要异步调用。
  2300. ''' </summary>
  2301. ''' <param name="Text">显示的文本。</param>
  2302. ''' <param name="CanRename">是否显示重命名选项。</param>
  2303. ''' <returns>用户做出的是否安装的决定。</returns>
  2304. ''' <remarks></remarks>
  2305. Public Function AutoSetupCheck(ByVal Text As String, Optional ByVal CanRename As Boolean = False) As Integer
  2306. Return MyMsgbox(Text, "自动安装确认", "覆盖", If(CanRename, "重命名", "取消"), If(CanRename, "取消", ""), True)
  2307. End Function
  2308. #End Region
  2309. #Region "设置"
  2310. ''' <summary>
  2311. ''' 切换页面隐藏。
  2312. ''' </summary>
  2313. ''' <remarks></remarks>
  2314. Public Sub SetupRefreshHidden()
  2315. frmMain.btnTopDown.Visibility = If(ReadIni("setup", "UiHiddenDownload", "False") = "True", Visibility.Collapsed, Visibility.Visible)
  2316. frmMain.btnTopSetup.Visibility = If(ReadIni("setup", "UiHiddenSetup", "False") = "True", Visibility.Collapsed, Visibility.Visible)
  2317. End Sub
  2318. ''' <summary>
  2319. ''' 切换背景图片的展示方式。
  2320. ''' </summary>
  2321. ''' <remarks></remarks>
  2322. Public Sub SetupRefreshBackground()
  2323. Select Case Val(ReadIni("setup", "UiBackgroundShow", "0"))
  2324. Case 0
  2325. '右下
  2326. frmMain.imgMainBg.HorizontalAlignment = HorizontalAlignment.Right
  2327. frmMain.imgMainBg.VerticalAlignment = VerticalAlignment.Bottom
  2328. frmMain.imgMainBg.Stretch = Stretch.None
  2329. Case 1
  2330. '左上
  2331. frmMain.imgMainBg.HorizontalAlignment = HorizontalAlignment.Left
  2332. frmMain.imgMainBg.VerticalAlignment = VerticalAlignment.Top
  2333. frmMain.imgMainBg.Stretch = Stretch.None
  2334. Case 2
  2335. '右上
  2336. frmMain.imgMainBg.HorizontalAlignment = HorizontalAlignment.Right
  2337. frmMain.imgMainBg.VerticalAlignment = VerticalAlignment.Top
  2338. frmMain.imgMainBg.Stretch = Stretch.None
  2339. Case 3
  2340. '居中
  2341. frmMain.imgMainBg.HorizontalAlignment = HorizontalAlignment.Center
  2342. frmMain.imgMainBg.VerticalAlignment = VerticalAlignment.Center
  2343. frmMain.imgMainBg.Stretch = Stretch.None
  2344. Case 4
  2345. '拉伸
  2346. frmMain.imgMainBg.HorizontalAlignment = HorizontalAlignment.Stretch
  2347. frmMain.imgMainBg.VerticalAlignment = VerticalAlignment.Stretch
  2348. frmMain.imgMainBg.Stretch = Stretch.Fill
  2349. Case 5
  2350. '适应
  2351. frmMain.imgMainBg.HorizontalAlignment = HorizontalAlignment.Stretch
  2352. frmMain.imgMainBg.VerticalAlignment = VerticalAlignment.Stretch
  2353. frmMain.imgMainBg.Stretch = Stretch.UniformToFill
  2354. End Select
  2355. End Sub
  2356. ''' <summary>
  2357. ''' 根据进行版本隔离返回某版本所需的游戏目录,以“\”结尾。
  2358. ''' </summary>
  2359. ''' <param name="Version"></param>
  2360. ''' <returns></returns>
  2361. ''' <remarks></remarks>
  2362. Public Function GetVersionFolder(ByVal Version As MCVersion) As String
  2363. Select Case Val(ReadIni("setup", "LaunchSplit", "0"))
  2364. Case 0
  2365. Return PATH_MC
  2366. Case 1
  2367. Return If(Version.Type = MCVersionType.FORGE, Version.Path, PATH_MC)
  2368. Case Else
  2369. Return Version.Path
  2370. End Select
  2371. End Function
  2372. #End Region
  2373. #Region "提示"
  2374. ''' <summary>
  2375. ''' 等待弹出的提示文本。
  2376. ''' </summary>
  2377. ''' <remarks></remarks>
  2378. Public WaitingHint As ArrayList = If(IsNothing(WaitingHint), New ArrayList, WaitingHint)
  2379. ''' <summary>
  2380. ''' 在窗口左下角弹出提示文本。
  2381. ''' </summary>
  2382. ''' <param name="Hint">要显示的提示。</param>
  2383. ''' <remarks></remarks>
  2384. Public Sub ShowHint(ByVal Hint As HintConverter)
  2385. If IsNothing(WaitingHint) Then WaitingHint = New ArrayList 'MDZZ这初始化也太坑了
  2386. For Each NowHint As HintConverter In WaitingHint
  2387. If Hint.Text = NowHint.Text Then Exit Sub
  2388. Next
  2389. WaitingHint.Add(Hint)
  2390. End Sub
  2391. ''' <summary>
  2392. ''' 在窗口左下角弹出提示文本。
  2393. ''' </summary>
  2394. ''' <param name="Text">要显示的提示。</param>
  2395. ''' <remarks></remarks>
  2396. Public Sub ShowHint(ByVal Text As String)
  2397. ShowHint(New HintConverter(Text))
  2398. End Sub
  2399. ''' <summary>
  2400. ''' 等待弹出的提示窗口。
  2401. ''' </summary>
  2402. ''' <remarks></remarks>
  2403. Public WaitingHintWindow As ArrayList = If(IsNothing(WaitingHintWindow), New ArrayList, WaitingHintWindow)
  2404. ''' <summary>
  2405. ''' 弹出提示窗口。
  2406. ''' </summary>
  2407. ''' <param name="Hint">要显示的提示文本。</param>
  2408. ''' <remarks></remarks>
  2409. Public Sub ShowHintWindow(ByVal Title As String, ByVal Hint As String)
  2410. frmMain.Dispatcher.Invoke(Sub()
  2411. If IsNothing(WaitingHintWindow) Then WaitingHintWindow = New ArrayList '初始化
  2412. If Not WaitingHintWindow.Contains({Title, Hint}) Then
  2413. WaitingHintWindow.Add({Title, Hint})
  2414. End If
  2415. End Sub)
  2416. End Sub
  2417. #End Region
  2418. #Region "统计与反馈"
  2419. Public SendInvokes As New ArrayList
  2420. Private LastPage As String = QN_SERVER & "stats.html"
  2421. ''' <summary>
  2422. ''' 发送页面数据。
  2423. ''' </summary>
  2424. ''' <param name="Name">统计的页面。</param>
  2425. ''' <remarks></remarks>
  2426. Public Sub SendPage(ByVal Name As String)
  2427. If MODE_DEVELOPER Then log("[System] 发送页面统计:" & Name)
  2428. If MODE_OFFLINE Or MODE_DEVELOPER Then Exit Sub
  2429. SendInvokes.Add("try{_czc.push([""_trackPageview"",""/" & Name & ".html"",""" & LastPage & """]);}catch (e){}")
  2430. LastPage = QN_SERVER & Name & ".html"
  2431. End Sub
  2432. ''' <summary>
  2433. ''' 发送事件统计。
  2434. ''' </summary>
  2435. ''' <remarks></remarks>
  2436. Public Sub SendStat(ByVal MainType As String, ByVal Action As String, Optional ByVal Lab As String = "", Optional ByVal Number As Integer = 0)
  2437. Try
  2438. MainType = MainType.Replace(vbCrLf, "").Replace("""", " ").Replace("\", "/")
  2439. Action = Action.Replace(vbCrLf, "").Replace("""", " ").Replace("\", "/")
  2440. Lab = Lab.Replace(vbCrLf, "").Replace("""", " ").Replace("\", "/")
  2441. If (Not AllowFeedback) And (Not MainType = "推荐源") Then Exit Sub
  2442. If MODE_DEVELOPER Then log("[System] 发送事件统计:" & MainType & " > " & Action & If(Lab = "", "", " > " & Lab) & "(" & Number & ")")
  2443. If MODE_OFFLINE Or MODE_DEVELOPER Then Exit Sub
  2444. SendInvokes.Add("try{_czc.push([""_trackEvent"",""" & MainType & """,""" & Action & """,""" & Lab & """," & Number & ",]);}catch (e){}")
  2445. Catch
  2446. End Try
  2447. End Sub
  2448. ''' <summary>
  2449. ''' 处理错误信息。
  2450. ''' </summary>
  2451. ''' <param name="ex"></param>
  2452. ''' <param name="description">描述文本,如“下载文件时出错”。</param>
  2453. ''' <param name="errorLevel">错误的严重程度。</param>
  2454. ''' <remarks></remarks>
  2455. Public Sub ExShow(ByVal ex As Exception, ByVal description As String, Optional ByVal errorLevel As ErrorLevel = ErrorLevel.DebugOnly, Optional ByVal msgboxText As String = "")
  2456. On Error Resume Next
  2457. '发送统计
  2458. If Not description.Contains("下载文件失败") Then SendStat("错误", GetStringFromEnum(errorLevel), description & ":" & GetStringFromException(ex), errorLevel)
  2459. '处理错误
  2460. Select Case errorLevel
  2461. Case modMain.ErrorLevel.Slient
  2462. '不提示用户
  2463. log("[Error] " & description & ":" & GetStringFromException(ex, MODE_DEVELOPER),, True)
  2464. Case modMain.ErrorLevel.DebugOnly
  2465. '提示调试模式用户
  2466. log("[Error] " & description & ":" & GetStringFromException(ex, True), True)
  2467. Case modMain.ErrorLevel.AllUsers
  2468. '提示所有用户
  2469. log("[Error] " & description & ":" & GetStringFromException(ex, True))
  2470. ShowHint(New HintConverter(description & ":" & GetStringFromException(ex), HintState.Critical))
  2471. Case modMain.ErrorLevel.MsgboxWithoutFeedback
  2472. '弹窗,不要求反馈
  2473. MyMsgbox(If(Not msgboxText = "", msgboxText & vbCrLf & vbCrLf, "") & "详细的错误信息:" & GetStringFromException(ex, True), description, IsWaitExit:=False)
  2474. Case modMain.ErrorLevel.MsgboxAndFeedback
  2475. '弹窗,要求反馈
  2476. If MyMsgbox(If(Not msgboxText = "", msgboxText & vbCrLf & vbCrLf, "") & "详细的错误信息:" & GetStringFromException(ex, True) & vbCrLf & vbCrLf & "你是否愿意反馈这个问题?", description, "反馈", "不反馈") = 1 Then
  2477. Feedback()
  2478. End If
  2479. Case modMain.ErrorLevel.Barrier
  2480. '尽可能显示错误信息,然后关闭程序
  2481. If MsgBox(If(Not msgboxText = "", msgboxText & vbCrLf & vbCrLf, "") & "详细的错误信息:" & GetStringFromException(ex, True) & vbCrLf & vbCrLf & "你是否愿意反馈这个问题?", MsgBoxStyle.YesNo + MsgBoxStyle.Critical, description) = MsgBoxResult.Yes Then
  2482. Feedback()
  2483. End If
  2484. End
  2485. End Select
  2486. End Sub
  2487. Public Enum ErrorLevel As Integer
  2488. ''' <summary>
  2489. ''' 正常情况下的常发错误。只记录 Log,不提示用户。
  2490. ''' </summary>
  2491. ''' <remarks></remarks>
  2492. Slient = 0
  2493. ''' <summary>
  2494. ''' 只需要提示调试模式下的用户。
  2495. ''' </summary>
  2496. ''' <remarks></remarks>
  2497. DebugOnly = 1
  2498. ''' <summary>
  2499. ''' 需要以弹出提示的方式提示所有用户。
  2500. ''' </summary>
  2501. ''' <remarks></remarks>
  2502. AllUsers = 2
  2503. ''' <summary>
  2504. ''' 需要以弹窗的方式提示所有用户,但是不要求反馈。
  2505. ''' </summary>
  2506. ''' <remarks></remarks>
  2507. MsgboxWithoutFeedback = 3
  2508. ''' <summary>
  2509. ''' 需要以弹窗的方式提示所有用户,并且要求反馈。
  2510. ''' </summary>
  2511. ''' <remarks></remarks>
  2512. MsgboxAndFeedback = 4
  2513. ''' <summary>
  2514. ''' 尽可能弹出提示,然后结束程序。
  2515. ''' </summary>
  2516. ''' <remarks></remarks>
  2517. Barrier = 5
  2518. End Enum
  2519. ''' <summary>
  2520. ''' 开始用户反馈。本函数会直接打开log文件与反馈网页。
  2521. ''' </summary>
  2522. Public Sub Feedback()
  2523. If MyMsgbox("PCL2 正在制作中,因此 PCL1 已经停止更新与维护,反馈通道已经关闭。" & vbCrLf & "你可在 http://afdian.net/@LTCat 查看 PCL2 当前制作进度。(制作进度日更,制作完成后依然免费下载)", "反馈提示", "查看 PCL2 制作进度", "返回") = 1 Then
  2524. Process.Start("https://afdian.net/@LTCat")
  2525. End If
  2526. 'Process.Start("https://www.wjx.cn/jq/14677608.aspx")
  2527. 'Shell("notepad", PATH & "PCL\log.txt")
  2528. End Sub
  2529. Public Sub FeedbackSetup()
  2530. Try
  2531. SendStat("反馈", "设置等级", ReadReg("SysLevel", "Default (0)"), ReadReg("SysLevel", "0"))
  2532. SendStat("反馈", "调试模式", ReadReg("SysTest", "Default (False)"), ReadReg("SysTest", "False") = "True")
  2533. SendStat("反馈", "检查更新", ReadIni("setup", "SysUpdate", "Default (True)"), ReadIni("setup", "SysUpdate", "True") = "True")
  2534. SendStat("反馈", "有更新时是否只提示", ReadIni("setup", "SysUpdateHint", "Default (True)"), ReadIni("setup", "SysUpdateHint", "True") = "True")
  2535. SendStat("反馈", "低内存警告", ReadIni("setup", "raSystemWarn", "Default (100)"), ReadIni("setup", "raSystemWarn", "100"))
  2536. SendStat("反馈", "接收测试版更新", ReadIni("setup", "SysUpdateTest", "Default (False)"), ReadIni("setup", "SysUpdateTest", "False") = "True")
  2537. SendStat("反馈", "启动器主题", ReadIni("setup", "UiTheme", "Default (0)"), ReadIni("setup", "UiTheme", "0"))
  2538. SendStat("反馈", "启用自定义背景", File.Exists(PATH & "PCL\back.png"), File.Exists(PATH & "PCL\back.png"))
  2539. SendStat("反馈", "启用自定义顶部栏", File.Exists(PATH & "PCL\top.png"), File.Exists(PATH & "PCL\top.png"))
  2540. SendStat("反馈", "启用 BGM", File.Exists(PATH & "PCL\bgm.wav") Or File.Exists(PATH & "PCL\bgm.mp3"), File.Exists(PATH & "PCL\bgm.wav") Or File.Exists(PATH & "PCL\bgm.mp3"))
  2541. SendStat("反馈", "背景透明度", ReadIni("setup", "UiBackgroundOpacity", "Default (50)"), ReadIni("setup", "UiBackgroundOpacity", "50"))
  2542. SendStat("反馈", "启动器透明度", ReadIni("setup", "UiLauncherOpacity", "Default (100)"), ReadIni("setup", "UiLauncherOpacity", "100"))
  2543. SendStat("反馈", "游戏窗口置顶", ReadReg("LaunchTopmost", "Default (False)"), ReadReg("LaunchTopmost", "False") = "True")
  2544. SendStat("反馈", "启动器可见性", ReadIni("setup", "LaunchVisibility", "Default (3)"), ReadIni("setup", "LaunchVisibility", "3"))
  2545. SendStat("反馈", "游戏进程优先级", ReadReg("LaunchLevel", "Default (1)"), ReadReg("LaunchLevel", "1"))
  2546. SendStat("反馈", "显示游戏日志", ReadIni("setup", "LaunchLog", "Default (False)"), ReadIni("setup", "LaunchLog", "False") = "True")
  2547. SendStat("反馈", "离线皮肤", ReadReg("LaunchSkin", "Default (3)"), ReadReg("LaunchSkin", "3"))
  2548. SendStat("反馈", "离线皮肤正版名", ReadReg("LaunchSkinName", "Default (None)"))
  2549. SendStat("反馈", "版本隔离", ReadIni("setup", "LaunchSplit", "Default (0)"), ReadIni("setup", "LaunchSplit", "0"))
  2550. SendStat("反馈", "游戏窗口模式", ReadIni("setup", "LaunchMode", "Default (0)"), ReadIni("setup", "LaunchMode", "0"))
  2551. SendStat("反馈", "Java 路径", ReadReg("SetupJavaPath", "Default (None)"))
  2552. SendStat("反馈", "最大内存", ReadReg("LaunchMaxRam", "Default (1024)"), ReadReg("LaunchMaxRam", "1024"))
  2553. SendStat("反馈", "电脑最大内存", Int(My.Computer.Info.TotalPhysicalMemory / 256 / 1024 / 1024) * 256 & "M", Int(My.Computer.Info.TotalPhysicalMemory / 256 / 1024 / 1024) * 256)
  2554. SendStat("反馈", "Java 版本", GetFileVersion(PATH_JAVA & "\javaw.exe"))
  2555. SendStat("反馈", "游戏版本列表源", ReadIni("setup", "DownVersion", "Default (0)"), ReadIni("setup", "DownVersion", "0"))
  2556. SendStat("反馈", "游戏数据文件源", ReadIni("setup", "DownAssets", "Default (0)"), ReadIni("setup", "DownAssets", "0"))
  2557. SendStat("反馈", "游戏组件源", ReadIni("setup", "DownMinecraft", "Default (1)"), ReadIni("setup", "DownMinecraft", "1"))
  2558. SendStat("反馈", "OptiFine 源", ReadIni("setup", "DownOptiFine", "Default (1)"), ReadIni("setup", "DownOptiFine", "1"))
  2559. SendStat("反馈", "Forge 源", ReadIni("setup", "DownForge", "Default (1)"), ReadIni("setup", "DownForge", "1"))
  2560. SendStat("反馈", "Forge 自动安装", ReadIni("setup", "DownForgeAction", "Default (1)"), ReadIni("setup", "DownForgeAction", "1"))
  2561. SendStat("反馈", "数据缺失提示", ReadIni("setup", "DownMinecraftAssetsHint", "Default (True)"), ReadIni("setup", "DownMinecraftAssetsHint", "True") = "True")
  2562. SendStat("反馈", "数据缺失自动下载", ReadIni("setup", "DownMinecraftAssetsAuto", "Default (True)"), ReadIni("setup", "DownMinecraftAssetsAuto", "True") = "True")
  2563. SendStat("反馈", "同时下载文件数", ReadIni("setup", "DownMaxinum", "Default (15)"), ReadIni("setup", "DownMaxinum", "15"))
  2564. SendStat("反馈", "游戏更新提示", ReadIni("setup", "HomeUpdate", "Default (True)"), ReadIni("setup", "HomeUpdate", "True") = "True")
  2565. SendStat("反馈", "游戏更新提示仅正式版", ReadIni("setup", "HomeUpdateRelease", "Default (False)"), ReadIni("setup", "HomeUpdateRelease", "False") = "True")
  2566. SendStat("反馈", "保存密码", ReadReg("HomeSave", "Default (False)"), ReadReg("HomeSave", "False") = "True")
  2567. SendStat("反馈", "自动登录", ReadIni("setup", "HomeAutologin", "Default (False)"), ReadIni("setup", "HomeAutologin", "False") = "True")
  2568. SendStat("反馈", "自动播放速度", ReadIni("setup", "raHomeAutoplaySpeed", "Default (1)"), ReadIni("setup", "raHomeAutoplaySpeed", "1"))
  2569. SendStat("反馈", "推荐源:PCL", ReadIni("setup", "HomePCLPush", "Default (True)"), ReadIni("setup", "HomePCLPush", "True") = "True")
  2570. SendStat("反馈", "推荐源:MCBBS", ReadIni("setup", "HomeMCBBSPush", "Default (True)"), ReadIni("setup", "HomeMCBBSPush", "True") = "True")
  2571. SendStat("反馈", "推荐源:贴吧", ReadIni("setup", "HomeTbPush", "Default (True)"), ReadIni("setup", "HomeTbPush", "True") = "True")
  2572. SendStat("反馈", "推荐源:Forum", ReadIni("setup", "HomeForumPush", "Default (False)"), ReadIni("setup", "HomeForumPush", "True") = "True")
  2573. SendStat("反馈", "推荐源:Mojang", ReadIni("setup", "HomeMojangPush", "Default (True)"), ReadIni("setup", "HomeMojangPush", "True") = "True")
  2574. SendStat("反馈", "推荐源:广告", ReadIni("setup", "HomeAdPush", "Default (True)"), ReadIni("setup", "HomeAdPush", "True") = "True")
  2575. SendStat("反馈", "启动器版本", VERSION_NAME, VERSION_CODE)
  2576. Catch ex As Exception
  2577. ExShow(ex, "发送用户反馈失败", ErrorLevel.Slient)
  2578. End Try
  2579. End Sub
  2580. #End Region
  2581. #Region "皮肤"
  2582. ''' <summary>
  2583. ''' 从官方 UUID 获取本地缓存的皮肤路径。如果失败返回空字符串。
  2584. ''' </summary>
  2585. ''' <returns></returns>
  2586. Public Function GetCacheSkinAddressByMojangUUID(UUID As String) As String
  2587. Dim SkinName = ReadIni("cache\skin\SkinName", UUID)
  2588. If SkinName = "" Then
  2589. Return ""
  2590. ElseIf SkinName = "Steve" Or SkinName = "Alex" Then
  2591. Return SkinName
  2592. Else
  2593. GetCacheSkinAddressByMojangUUID = PATH & "PCL\cache\skin\" & SkinName & ".png"
  2594. If Not File.Exists(GetCacheSkinAddressByMojangUUID) Then Return ""
  2595. End If
  2596. End Function
  2597. ''' <summary>
  2598. ''' 下载对应官方 UUID 的皮肤并返回文件路径。如果失败返回空字符串。
  2599. ''' </summary>
  2600. ''' <param name="UUID"></param>
  2601. ''' <returns></returns>
  2602. Public Function DownloadSkin(UUID As String) As String
  2603. Try
  2604. '尝试读取缓存的皮肤
  2605. Dim CacheSkinAddress As String = GetCacheSkinAddressByMojangUUID(UUID)
  2606. If Not CacheSkinAddress = "" Then Return CacheSkinAddress
  2607. '获取皮肤下载地址
  2608. '获取皮肤地址
  2609. Dim StringConv = GetWebsiteCode("https://sessionserver.mojang.com/session/minecraft/profile/" & UUID, Encoding.Default)
  2610. '如果返回为空,则为离线皮肤
  2611. If StringConv = "" Then Return GetSkinTypeFromUUID(UUID)
  2612. '处理皮肤地址
  2613. StringConv = StringConv.Replace(" ", "")
  2614. StringConv = Mid(StringConv, StringConv.IndexOf("textures"",""value"":""") + 1).Replace("textures"",""value"":""", "")
  2615. StringConv = Mid(StringConv, 1, StringConv.IndexOf("""")).Replace(" ", "")
  2616. StringConv = System.Text.Encoding.GetEncoding("utf-8").GetString(Convert.FromBase64String(StringConv))
  2617. StringConv = StringConv.Replace(" ", "")
  2618. If Not StringConv.Contains("""url"":""") Then Return GetSkinTypeFromUUID(UUID)
  2619. StringConv = Mid(StringConv, StringConv.IndexOf("""url"":""") + 1).Replace("""url"":""", "")
  2620. StringConv = Mid(StringConv, 1, StringConv.IndexOf("""")).Replace(" ", "")
  2621. '下载皮肤
  2622. Dim FileName As String = Mid(StringConv, StringConv.LastIndexOf("/") + 2)
  2623. If Not File.Exists(PATH & "PCL\cache\skin\" & FileName & ".png") Then
  2624. DownloadFile(StringConv, PATH & "PCL\cache\skin\" & FileName & ".png" & DOWNLOADING_END)
  2625. File.Delete(PATH & "PCL\cache\skin\" & FileName & ".png")
  2626. FileSystem.Rename(PATH & "PCL\cache\skin\" & FileName & ".png" & DOWNLOADING_END, PATH & "PCL\cache\skin\" & FileName & ".png")
  2627. log("[System] 皮肤下载成功:" & FileName)
  2628. End If
  2629. WriteIni("cache\skin\SkinName", UUID, FileName)
  2630. Return PATH & "PCL\cache\skin\" & FileName & ".png"
  2631. Catch ex As Exception
  2632. ExShow(ex, "下载皮肤失败(" & UUID & ")", ErrorLevel.Slient)
  2633. Return ""
  2634. End Try
  2635. End Function
  2636. ''' <summary>
  2637. ''' 获取UUID对应的离线皮肤,返回“Steve”或“Alex”。
  2638. ''' </summary>
  2639. ''' <param name="UUID"></param>
  2640. ''' <returns></returns>
  2641. ''' <remarks></remarks>
  2642. Public Function GetSkinTypeFromUUID(ByVal UUID As String) As String
  2643. If Not UUID.Length = 32 Then Return "Steve"
  2644. Dim a = Integer.Parse(UUID(7), Globalization.NumberStyles.AllowHexSpecifier)
  2645. Dim b = Integer.Parse(UUID(15), Globalization.NumberStyles.AllowHexSpecifier)
  2646. Dim c = Integer.Parse(UUID(23), Globalization.NumberStyles.AllowHexSpecifier)
  2647. Dim d = Integer.Parse(UUID(31), Globalization.NumberStyles.AllowHexSpecifier)
  2648. Return If(((a Xor b) Xor (c Xor d)) Mod 2, "Alex", "Steve")
  2649. End Function
  2650. #End Region
  2651. Public Delegate Sub RefreshThemeInvoke()
  2652. ''' <summary>刷新主题。</summary>
  2653. ''' <remarks></remarks>
  2654. Public Sub RefreshTheme()
  2655. Try
  2656. '读取数据
  2657. Dim LeftbarUri As String = PATH_IMAGE & "LeftBar-BG_Blue.png"
  2658. frmMain.imgMainBg.Source = Nothing
  2659. If File.Exists(PATH & "PCL\top.png") Then LeftbarUri = PATH & "PCL\top.png"
  2660. If File.Exists(PATH & "PCL\back.png") Then
  2661. frmMain.imgMainBg.Source = New MyBitmap(PATH & "PCL\back.png")
  2662. SetupRefreshBackground()
  2663. End If
  2664. Select Case Val(ReadIni("setup", "UiTheme", "0"))
  2665. Case 0
  2666. Application.Current.Resources("Color1") = New SolidColorBrush(Color.FromRgb(213, 233, 255))
  2667. Application.Current.Resources("Color2") = New SolidColorBrush(Color.FromRgb(106, 177, 255))
  2668. Application.Current.Resources("Color3") = New SolidColorBrush(Color.FromRgb(0, 121, 255))
  2669. Application.Current.Resources("Color4") = New SolidColorBrush(Color.FromRgb(0, 81, 170))
  2670. Application.Current.Resources("Color5") = New SolidColorBrush(Color.FromRgb(0, 40, 85))
  2671. log("[System] 主题配色:蓝色")
  2672. Case 1
  2673. LeftbarUri = PATH_IMAGE & "LeftBar-BG_Black.png"
  2674. Application.Current.Resources("Color1") = New SolidColorBrush(Color.FromRgb(212, 212, 212))
  2675. Application.Current.Resources("Color2") = New SolidColorBrush(Color.FromRgb(148, 148, 148))
  2676. Application.Current.Resources("Color3") = New SolidColorBrush(Color.FromRgb(127, 127, 127))
  2677. Application.Current.Resources("Color4") = New SolidColorBrush(Color.FromRgb(90, 90, 90))
  2678. Application.Current.Resources("Color5") = New SolidColorBrush(Color.FromRgb(42, 42, 42))
  2679. log("[System] 主题配色:黑色")
  2680. Case 2
  2681. LeftbarUri = PATH_IMAGE & "LeftBar-BG_Orange.png"
  2682. Application.Current.Resources("Color1") = New SolidColorBrush(Color.FromRgb(255, 232, 213))
  2683. Application.Current.Resources("Color2") = New SolidColorBrush(Color.FromRgb(255, 168, 96))
  2684. Application.Current.Resources("Color3") = New SolidColorBrush(Color.FromRgb(255, 126, 21))
  2685. Application.Current.Resources("Color4") = New SolidColorBrush(Color.FromRgb(191, 86, 0))
  2686. Application.Current.Resources("Color5") = New SolidColorBrush(Color.FromRgb(106, 48, 0))
  2687. log("[System] 主题配色:橙色")
  2688. Case 3
  2689. LeftbarUri = PATH_IMAGE & "LeftBar-BG_Green.png"
  2690. Application.Current.Resources("Color1") = New SolidColorBrush(Color.FromRgb(213, 255, 217))
  2691. Application.Current.Resources("Color2") = New SolidColorBrush(Color.FromRgb(97, 233, 111))
  2692. Application.Current.Resources("Color3") = New SolidColorBrush(Color.FromRgb(43, 213, 60))
  2693. Application.Current.Resources("Color4") = New SolidColorBrush(Color.FromRgb(29, 141, 40))
  2694. Application.Current.Resources("Color5") = New SolidColorBrush(Color.FromRgb(15, 70, 20))
  2695. log("[System] 主题配色:绿色")
  2696. Case 4
  2697. Application.Current.Resources("Color1") = New SolidColorBrush(Color.FromRgb(ReadIni("setup", "UiThemeColorR1", Application.Current.Resources("ColorE1").R), ReadIni("setup", "UiThemeColorG1", Application.Current.Resources("ColorE1").G), ReadIni("setup", "UiThemeColorB1", Application.Current.Resources("ColorE1").B)))
  2698. Application.Current.Resources("Color2") = New SolidColorBrush(Color.FromRgb(ReadIni("setup", "UiThemeColorR2", Application.Current.Resources("ColorE2").R), ReadIni("setup", "UiThemeColorG2", Application.Current.Resources("ColorE2").G), ReadIni("setup", "UiThemeColorB2", Application.Current.Resources("ColorE2").B)))
  2699. Application.Current.Resources("Color3") = New SolidColorBrush(Color.FromRgb(ReadIni("setup", "UiThemeColorR3", Application.Current.Resources("ColorE3").R), ReadIni("setup", "UiThemeColorG3", Application.Current.Resources("ColorE3").G), ReadIni("setup", "UiThemeColorB3", Application.Current.Resources("ColorE3").B)))
  2700. Application.Current.Resources("Color4") = New SolidColorBrush(Color.FromRgb(ReadIni("setup", "UiThemeColorR4", Application.Current.Resources("ColorE4").R), ReadIni("setup", "UiThemeColorG4", Application.Current.Resources("ColorE4").G), ReadIni("setup", "UiThemeColorB4", Application.Current.Resources("ColorE4").B)))
  2701. Application.Current.Resources("Color5") = New SolidColorBrush(Color.FromRgb(ReadIni("setup", "UiThemeColorR5", Application.Current.Resources("ColorE5").R), ReadIni("setup", "UiThemeColorG5", Application.Current.Resources("ColorE5").G), ReadIni("setup", "UiThemeColorB5", Application.Current.Resources("ColorE5").B)))
  2702. log("[System] 主题配色:自定义")
  2703. Case 100
  2704. LeftbarUri = PATH_IMAGE & "LeftBar-BG_Hunluan.png"
  2705. Application.Current.Resources("Color1") = New SolidColorBrush(Color.FromRgb(248, 231, 191))
  2706. Application.Current.Resources("Color2") = New SolidColorBrush(Color.FromRgb(244, 208, 125))
  2707. Application.Current.Resources("Color3") = New SolidColorBrush(Color.FromRgb(228, 165, 16))
  2708. Application.Current.Resources("Color4") = New SolidColorBrush(Color.FromRgb(182, 130, 20))
  2709. Application.Current.Resources("Color5") = New SolidColorBrush(Color.FromRgb(102, 71, 0))
  2710. log("[System] 主题配色:混乱")
  2711. Case 101
  2712. LeftbarUri = PATH_IMAGE & "LeftBar-BG_DeathBlue.png"
  2713. Application.Current.Resources("Color1") = New SolidColorBrush(Color.FromRgb(209, 234, 254))
  2714. Application.Current.Resources("Color2") = New SolidColorBrush(Color.FromRgb(71, 171, 252))
  2715. Application.Current.Resources("Color3") = New SolidColorBrush(Color.FromRgb(3, 134, 241))
  2716. Application.Current.Resources("Color4") = New SolidColorBrush(Color.FromRgb(0, 108, 194))
  2717. Application.Current.Resources("Color5") = New SolidColorBrush(Color.FromRgb(0, 73, 45))
  2718. log("[System] 主题配色:死机蓝")
  2719. End Select
  2720. Application.Current.Resources("ColorE1") = Application.Current.Resources("Color1").Color
  2721. Application.Current.Resources("ColorE2") = Application.Current.Resources("Color2").Color
  2722. Application.Current.Resources("ColorE3") = Application.Current.Resources("Color3").Color
  2723. Application.Current.Resources("ColorE4") = Application.Current.Resources("Color4").Color
  2724. Application.Current.Resources("ColorE5") = Application.Current.Resources("Color5").Color
  2725. '改变控件图片
  2726. If Not LeftbarUri = "" Then CType(frmMain.panTop.Background, Object).ImageSource = New MyBitmap(LeftbarUri)
  2727. CType(frmMain.panTop.Background, Object).Stretch = Stretch.None
  2728. CType(frmMain.panTop.Background, Object).TileMode = TileMode.Tile
  2729. CType(CType(frmMain.panTop.Background, Object), ImageBrush).Viewport = (New RectConverter()).ConvertFromString("0,0," & CType(CType(frmMain.panTop.Background, Object).ImageSource, ImageSource).Width & "," & CType(CType(frmMain.panTop.Background, Object).ImageSource, ImageSource).Height)
  2730. '改变已有控件
  2731. 'Dim E2NoAlpha As Color = Application.Current.Resources("ColorE2")
  2732. 'E2NoAlpha.A = 1
  2733. 'If Not IsNothing(frmHomeRight.SwapOldLab) Then CType(frmHomeRight.SwapOldLab.Background, SolidColorBrush).SetCurrentValue(SolidColorBrush.ColorProperty, E2NoAlpha)
  2734. 'If Not IsNothing(frmHomeRight.SwapVersionLab) Then CType(frmHomeRight.SwapVersionLab.Background, SolidColorBrush).SetCurrentValue(SolidColorBrush.ColorProperty, E2NoAlpha)
  2735. Catch ex As Exception
  2736. ExShow(ex, "刷新主题失败", ErrorLevel.Barrier)
  2737. End Try
  2738. End Sub
  2739. ''' <summary>
  2740. ''' 以正常方式结束程序运行,这会输出log与执行动画。
  2741. ''' </summary>
  2742. ''' <remarks></remarks>
  2743. Public Sub EndNormal()
  2744. AniStart({
  2745. AaOpacity(frmMain, -1, 150),
  2746. AaScaleTransform(frmMain.panAllBack, -0.05, 150,, New AniEaseJumpStart(0.4)),
  2747. AaCode({"End"}, 250)
  2748. }, "EndAll")
  2749. log("[System] 收到正常关闭指令")
  2750. End Sub
  2751. ''' <summary>
  2752. ''' 强制暴力结束程序执行。
  2753. ''' </summary>
  2754. ''' <remarks></remarks>
  2755. Public Sub EndForce()
  2756. On Error Resume Next
  2757. Process.GetCurrentProcess.Kill()
  2758. End
  2759. My.Application.Shutdown()
  2760. frmMain.Close()
  2761. frmStart.Close()
  2762. End Sub
  2763. '动画事件
  2764. Public Sub AaCodeCall(ByVal type As String, ByVal data As Array)
  2765. Select Case type
  2766. Case "HideInfoBox"
  2767. data(1).Hide()
  2768. Case "PageChange"
  2769. frmMain.PageChange(data(1))
  2770. End Select
  2771. End Sub
  2772. Private LogLock As New Object
  2773. ''' <summary>
  2774. ''' 输出Log。
  2775. ''' </summary>
  2776. ''' <param name="LogText">Log文本。</param>
  2777. ''' <param name="Notice">是否为重要记录,如果为是则会给调试模式用户发送提示。</param>
  2778. ''' <remarks></remarks>
  2779. Public Sub Log(ByVal LogText As String, Optional ByVal Notice As Boolean = False, Optional DeveloperNotice As Boolean = False)
  2780. Try
  2781. Dim OutputText = "[" & GetTime() & "] " & LogText
  2782. Debug.WriteLine(OutputText)
  2783. If Not File.Exists(PATH & "PCL\log.txt") Then
  2784. File.Create(PATH & "PCL\log.txt").Dispose()
  2785. End If
  2786. SyncLock LogLock
  2787. Using Writter As New StreamWriter(PATH & "PCL\log.txt", True)
  2788. Writter.WriteLine(OutputText)
  2789. Writter.Close()
  2790. End Using
  2791. End SyncLock
  2792. If Notice And MODE_DEBUG Then ShowHint(New HintConverter("[调试模式] " & LogText.Replace("[Error] ", ""), HintState.Warn))
  2793. If DeveloperNotice And MODE_DEVELOPER Then ShowHint(New HintConverter("[开发者模式] " & LogText.Replace("[Error] ", ""), HintState.Info))
  2794. Catch
  2795. End Try
  2796. End Sub
  2797. Public UpdateState As LoadState = LoadState.Waiting
  2798. ''' <summary>
  2799. ''' 下载PCL版本更新。
  2800. ''' </summary>
  2801. ''' <remarks></remarks>
  2802. Public Sub DownloadUpdate()
  2803. UpdateState = LoadState.Loading
  2804. log("[System] 下载更新开始")
  2805. SendStat("反馈", "升级", VERSION_NAME, VERSION_CODE)
  2806. WebStart({New WebRequireFile With {
  2807. .WebURLs = New ArrayList From {
  2808. TX_SREVER_2 & If(ReadIni("setup", "SysUpdateTest", "False") = "True", "pcl_snapshot", "pcl_release") & ".zip",
  2809. TX_SREVER_1 & If(ReadIni("setup", "SysUpdateTest", "False") = "True", "pcl_snapshot", "pcl_release") & ".zip"
  2810. },
  2811. .LocalFolder = PATH & "PCL\", .LocalName = "pcl.zip", .KnownFileSize = 256 * 1024}
  2812. }, "PCL 更新", Sub()
  2813. '下载成功
  2814. Try
  2815. If Directory.Exists(PATH & "PCL\Update") Then Directory.Delete(PATH & "PCL\Update", True)
  2816. Directory.CreateDirectory(PATH & "PCL\Update")
  2817. Using zip As New ZipFile(PATH & "PCL\pcl.zip", Encoding.Default)
  2818. zip.ExtractAll(PATH & "PCL\Update", ExtractExistingFileAction.OverwriteSilently)
  2819. End Using
  2820. File.Delete(PATH & "PCL\pcl.zip")
  2821. OutputFileInResource("PCLAM", PATH & "PCL\PCL Admin Manager.exe", False)
  2822. Dim Arguments As String = "Auto Update:" & GetPathFromFullPath(Forms.Application.ExecutablePath) & "|" & Process.GetCurrentProcess.Id
  2823. Shell(PATH & "PCL\PCL Admin Manager.exe", Arguments)
  2824. UpdateState = LoadState.Loaded
  2825. EndForce()
  2826. Catch ex As Exception
  2827. ShowHint(New HintConverter("更新失败:" & GetStringFromException(ex), HintState.Critical))
  2828. log("[System] 更新失败:" & GetStringFromException(ex, True), True)
  2829. UpdateState = LoadState.Failed
  2830. End Try
  2831. End Sub, Sub()
  2832. '下载失败
  2833. ShowHint(New HintConverter("下载更新失败", HintState.Critical))
  2834. UpdateState = LoadState.Failed
  2835. End Sub, WebRequireSize.AtLeast)
  2836. End Sub
  2837. Private LastRefreshOffline As Boolean = False
  2838. ''' <summary>
  2839. ''' 刷新离线模式状态。
  2840. ''' </summary>
  2841. ''' <remarks></remarks>
  2842. Public Sub RefreshOffline()
  2843. '刷新状态
  2844. If My.Computer.Network.IsAvailable Then
  2845. MODE_OFFLINE = ReadIni("setup", "SysOffline", "False")
  2846. Else
  2847. MODE_OFFLINE = True
  2848. End If
  2849. '检测是否变化
  2850. If LastRefreshOffline = MODE_OFFLINE Then Exit Sub
  2851. '各种UI的变化
  2852. On Error Resume Next
  2853. If Not IsNothing(frmMain.labTopVer) Then frmMain.labTopVer.Content = VERSION_NAME & If(MODE_DEVELOPER, " | 开发者模式", If(MODE_DEBUG, " | 调试模式", "")) & If(MODE_OFFLINE, " | 离线模式", "")
  2854. If Not IsNothing(frmHomeLeft) Then frmHomeLeft.ChangeWidth()
  2855. If MODE_OFFLINE And Not IsNothing(frmHomeRight) Then frmHomeRight.ChangeLoginMethod(LoginMethods.Legacy)
  2856. '更新状态
  2857. LastRefreshOffline = MODE_OFFLINE
  2858. End Sub
  2859. ''' <summary>
  2860. ''' 检查MC版本。
  2861. ''' </summary>
  2862. ''' <param name="Version">至少包含完整路径的MCVersion类。</param>
  2863. ''' <param name="CheckInherit">是否对依赖版本进行递归检查。</param>
  2864. ''' <remarks></remarks>
  2865. Public Sub CheckMCVersion(ByRef Version As MCVersion, Optional ByVal CheckInherit As Boolean = False)
  2866. '检查Json文件
  2867. If Not File.Exists(Version.Path & Version.Name & ".json") Then
  2868. If File.Exists(Version.Path & Version.Name & ".jar") Then
  2869. '存在Jar,但是不存在Json
  2870. Version.VersionCheckResult = VersionCheckState.JSON_NOT_EXIST
  2871. Else
  2872. 'Jar与Json均不存在
  2873. Version.VersionCheckResult = VersionCheckState.EMPTY_FOLDER
  2874. End If
  2875. Exit Sub
  2876. End If
  2877. '尝试读取Json
  2878. Try
  2879. If Version.JsonText.Length = 0 Then
  2880. End If
  2881. Catch
  2882. Version.VersionCheckResult = VersionCheckState.JSON_CANT_READ
  2883. Exit Sub
  2884. End Try
  2885. '检查Assets与依赖版本
  2886. Try
  2887. Version.InheritVersion = If(Version.Json("inheritsFrom"), "").ToString
  2888. If IsNothing(Version.Json("assets")) Then
  2889. If Version.InheritVersion = "" Then
  2890. Version.Assets = ""
  2891. Else
  2892. Version.Assets = If(New MCVersion(Version.InheritVersion).Json("assets"), "").ToString
  2893. End If
  2894. Else
  2895. Version.Assets = Version.Json("assets")
  2896. End If
  2897. Catch
  2898. Version.Assets = ""
  2899. End Try
  2900. If Not Version.InheritVersion = "" Then
  2901. '存在依赖版本
  2902. If Not Directory.Exists(PATH_MC & "versions\" & Version.InheritVersion) Then
  2903. '依赖版本不存在
  2904. Version.VersionCheckResult = VersionCheckState.INHERITS_NOT_EXIST
  2905. Exit Sub
  2906. End If
  2907. '检查依赖版本问题
  2908. If CheckInherit Then
  2909. Dim InheritVersion As New MCVersion(Version.InheritVersion)
  2910. CheckMCVersion(InheritVersion)
  2911. If Not InheritVersion.VersionCheckResult = VersionCheckState.NO_PROBLEM Then
  2912. '依赖版本存在问题
  2913. Version.VersionCheckResult = VersionCheckState.INHERITS_EXCEPTION
  2914. Exit Sub
  2915. End If
  2916. End If
  2917. End If
  2918. '获取全部引用
  2919. Dim LibrariesName As New ArrayList
  2920. Try
  2921. For Each File As JToken In Version.Json("libraries")
  2922. LibrariesName.Add(File("name").ToString)
  2923. Next
  2924. Catch
  2925. Version.VersionCheckResult = VersionCheckState.JSON_CANT_READ
  2926. Exit Sub
  2927. End Try
  2928. '获取主Jar路径
  2929. For Each Library As String In LibrariesName
  2930. If ReadIni("setup", "LaunchMending", "True") Then
  2931. '允许自动修复
  2932. If Library.Contains("net.minecraftforge") Or Library.Contains("optifine:OptiFine") Then
  2933. Version.VersionCheckResult = VersionCheckState.NO_PROBLEM
  2934. Exit Sub
  2935. End If
  2936. Else
  2937. '不允许自动修复
  2938. If Library.Contains("net.minecraftforge") Or Library.Contains("optifine:OptiFine") Then
  2939. '找到主Jar
  2940. If File.Exists(GetPathFromLibrary(Library)) Then
  2941. Version.VersionCheckResult = VersionCheckState.NO_PROBLEM
  2942. Else
  2943. Version.VersionCheckResult = VersionCheckState.JAR_NOT_EXIST
  2944. End If
  2945. Exit Sub
  2946. End If
  2947. End If
  2948. Next
  2949. '主Jar为原版
  2950. If File.Exists(Version.Path & Version.Name & ".jar") Then
  2951. Version.VersionCheckResult = VersionCheckState.NO_PROBLEM
  2952. Else
  2953. Version.VersionCheckResult = VersionCheckState.JAR_NOT_EXIST
  2954. End If
  2955. End Sub
  2956. ''' <summary>
  2957. ''' 从Json文件中的Library名获取文件所在的完整路径。
  2958. ''' </summary>
  2959. ''' <param name="Library"></param>
  2960. ''' <returns></returns>
  2961. ''' <remarks></remarks>
  2962. Public Function GetPathFromLibrary(ByVal Library As String) As String
  2963. Dim SourceArray = Library.Split(":")
  2964. Return PATH_MC & "libraries\" &
  2965. SourceArray(0).Replace(".", "\") & "\" &
  2966. SourceArray(1) & "\" &
  2967. SourceArray(2) & "\" &
  2968. SourceArray(1) & "-" & SourceArray(2) & ".jar"
  2969. End Function
  2970. Private IsSettingJavaEnvironment As Boolean = False
  2971. ''' <summary>
  2972. ''' 配置Java运行环境。必须在非主线程调用。
  2973. ''' </summary>
  2974. ''' <remarks></remarks>
  2975. Public Sub SetJavaEnvironment()
  2976. If IsSettingJavaEnvironment Then Exit Sub
  2977. IsSettingJavaEnvironment = True
  2978. '处理环境变量字符串,包括去重、去空白
  2979. Dim Env As String = PathEnv
  2980. Dim EnvironArray As Object() = ArrayNoDouble(Split(Env.Replace(";;", ";") & ";" & PATH_JAVA, ";")).ToArray
  2981. Dim NewEnv As String = Join(EnvironArray, ";").Replace(";;", ";")
  2982. Try
  2983. log("[System] 设置环境变量:" & NewEnv)
  2984. OutputFileInResource("PCLAM", PATH & "PCL\PCL Admin Manager.exe", False)
  2985. Process.Start(PATH & "PCL\PCL Admin Manager.exe", "Set Environment Variable:" & NewEnv)
  2986. PathEnv = NewEnv
  2987. ShowHint(New HintConverter("正在配置游戏环境,如果有安全提示请允许!(如果反复出现本提示,重启电脑即可)", HintState.Warn))
  2988. Catch ex As Exception
  2989. PATH_JAVA = ""
  2990. ExShow(ex, "设置环境变量时出现异常")
  2991. ShowHint(New HintConverter("配置游戏环境失败:" & GetStringFromException(ex) & "(尝试重启电脑或关闭杀毒软件)", HintState.Critical))
  2992. IsSettingJavaEnvironment = False
  2993. Exit Sub
  2994. End Try
  2995. ''等待并检查
  2996. 'For i As Integer = 1 To 10
  2997. ' Dim a = PathEnv
  2998. ' Dim b = Mid(PATH_JAVA, 1, Len(PATH_JAVA) - 1)
  2999. ' If PathEnv.Contains(Mid(PATH_JAVA, 1, Len(PATH_JAVA) - 1)) Then
  3000. ' ShowHint(New HintConverter("配置游戏环境成功!", HintState.FINISH))
  3001. ' IsSettingJavaEnvironment = False
  3002. ' Exit Sub
  3003. ' Else
  3004. ' Thread.Sleep(2000)
  3005. ' End If
  3006. 'Next i
  3007. 'ShowHint(New HintConverter("配置游戏环境失败!请尝试重启PCL或关闭杀毒软件。", HintState.CRITICAL))
  3008. IsSettingJavaEnvironment = False
  3009. End Sub
  3010. End Module