__init__.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. # -*- coding: utf-8 -*-
  2. """
  3. Package /home/cpi/games/xxx/yyy.zip ,only support in zip
  4. com_pkg_info /home/cpi/launcher/Menu/GameShell/xxxx/compkginfo.json
  5. use https://jsonlint.com/ to validate first in case syntax err
  6. ```
  7. {
  8. "NotFoundMsg":["Please Go to \n|None|varela14|True",
  9. "https://www.lexaloffle.com/pico-8.php|URL|None|True|True",
  10. "buy a pico-8 raspi and put zip into \n/home/cpi/games/PICO-8"]
  11. "MD5":{"pico-8_0.1.11g_raspi.zip":"a3f2995cf117499f880bd964d6a0e1f2","pico-8_0.1.11g_amd64.zip":"6726141c784afd4a41be6b7414c1b932"}
  12. }
  13. ```
  14. """
  15. import pygame
  16. #import validators
  17. import os
  18. import commands
  19. from UI.constants import Width,Height,ICON_TYPES,RUNEVT,RESTARTUI
  20. #from UI.simple_name_space import SimpleNamespace
  21. from UI.page import Page
  22. from UI.label import Label
  23. from UI.icon_item import IconItem
  24. from UI.icon_pool import MyIconPool
  25. from UI.keys_def import CurKeys,IsKeyMenuOrB,IsKeyStartOrA
  26. from UI.skin_manager import MySkinManager
  27. from UI.lang_manager import MyLangManager
  28. from UI.text_bulletinboard import Textbulletinboard,Text
  29. from UI.util_funcs import FileExists
  30. class NotFoundPage(Page):
  31. _FootMsg = ["Nav","","","Back",""]
  32. _BG = "pico8_notfound"
  33. _Leader = None
  34. _Padding = pygame.Rect(0,12,0,6)
  35. def Init(self):
  36. self._PosX = self._Index*self._Screen._Width
  37. self._Width = self._Screen._Width
  38. self._Height = self._Screen._Height
  39. self._CanvasHWND = self._Screen._CanvasHWND
  40. self._BGpng = IconItem()
  41. self._BGpng._ImgSurf = MyIconPool.GiveIconSurface(self._BG)
  42. self._BGpng._MyType = ICON_TYPES["STAT"]
  43. self._BGpng._Parent = self
  44. #print( MyIconPool.Width(self._BG),MyIconPool.Height(self._BG) )
  45. self._BGpng.Adjust(0,0,MyIconPool.Width(self._BG),MyIconPool.Height(self._BG),0)
  46. self._Board = Textbulletinboard()
  47. self._Board._PosX = 4
  48. self._Board._PosY = 100
  49. self._Board._Width= self._Width - 4*2
  50. self._Board._Height = 200
  51. self._Board._CanvasHWND = self._CanvasHWND
  52. self._Board._Align = "Center"
  53. self._Board._RowPitch =28
  54. self._Board.Init()
  55. if self._Leader!= None and self._Leader._ComPkgInfo != None:
  56. if "NotFoundMsg" in self._Leader._ComPkgInfo:
  57. d = []
  58. for i, v in enumerate(self._Leader._ComPkgInfo["NotFoundMsg"]):
  59. Color = None
  60. Font = None
  61. Bold = False
  62. Und = False
  63. Txt = ""
  64. parts = v.split("|")
  65. if len(parts) > 0:
  66. Txt = parts[0]
  67. if len(parts) == 2:
  68. if parts[1] != "None":
  69. Color = MySkinManager.GiveColor(parts[1])
  70. elif len(parts) == 3:
  71. if parts[1] != "None":
  72. Color = MySkinManager.GiveColor(parts[1])
  73. if parts[2] != "None":
  74. Font = MyLangManager.TrFont(parts[2])
  75. elif len(parts) == 4:
  76. if parts[1] != "None":
  77. Color = MySkinManager.GiveColor(parts[1])
  78. if parts[2] != "None":
  79. Font = MyLangManager.TrFont(parts[2])
  80. if parts[3] == "True":
  81. Bold = True
  82. elif len(parts) == 5:
  83. if parts[1] != "None":
  84. Color = MySkinManager.GiveColor(parts[1])
  85. if parts[2] != "None":
  86. Font = MyLangManager.TrFont(parts[2])
  87. if parts[3] == "True":
  88. Bold = True
  89. if parts[4] == "True":
  90. Und = True
  91. a = Text(Txt,Color,Font,Bold,Und)
  92. d = d + a.Words()
  93. self._Board.SetAndBlitText(d)
  94. def KeyDown(self,event):
  95. # if event.key == CurKeys["A"] or event.key == CurKeys["Menu"]:
  96. if IsKeyMenuOrB(event.key):
  97. self.ReturnToUpLevelPage()
  98. self._Screen.Draw()
  99. self._Screen.SwapAndShow()
  100. return
  101. def Draw(self):
  102. self.ClearCanvas()
  103. if self._BGpng != None:
  104. self._BGpng.NewCoord((self._Width-self._BGpng._Width)/2,self._Padding.y )
  105. self._BGpng.DrawTopLeft()
  106. self._Board._PosY = self._BGpng._Height+self._Padding.y+self._Padding.h
  107. else:
  108. self._Board._PosY = self._Padding.y
  109. self._Board.Draw()
  110. class HashErrPage(Page):
  111. _FootMsg = ["Nav","","","Cancel","Continue"]
  112. _BG ="pico8_md5_err"
  113. _Leader = None
  114. _Padding = pygame.Rect(0,12,0,6)
  115. def Init(self):
  116. self._PosX = self._Index*self._Screen._Width
  117. self._Width = self._Screen._Width
  118. self._Height = self._Screen._Height
  119. self._CanvasHWND = self._Screen._CanvasHWND
  120. self._BGpng = IconItem()
  121. self._BGpng._ImgSurf = MyIconPool.GiveIconSurface(self._BG)
  122. self._BGpng._MyType = ICON_TYPES["STAT"]
  123. self._BGpng._Parent = self
  124. self._BGpng.Adjust(0,0,MyIconPool.Width(self._BG),MyIconPool.Height(self._BG),0)
  125. self._Board = Textbulletinboard()
  126. self._Board._PosX = 4
  127. self._Board._PosY = self._Height/2 - 30
  128. self._Board._Width= self._Width - 4*2
  129. self._Board._Height = 100
  130. self._Board._CanvasHWND = self._CanvasHWND
  131. self._Board._RowPitch =28
  132. self._Board._Align = "Center"
  133. self._Board.Init()
  134. if self._Leader!= None and self._Leader._ComPkgInfo != None:
  135. if "HashErrMsg" in self._Leader._ComPkgInfo:
  136. d = []
  137. for i, v in enumerate(self._Leader._ComPkgInfo["HashErrMsg"]):
  138. Color = None
  139. Font = None
  140. Bold = False
  141. Und = False
  142. Txt = ""
  143. parts = v.split("|")
  144. if len(parts) > 0:
  145. Txt = parts[0]
  146. if len(parts) == 2:
  147. if parts[1] != "None":
  148. Color = MySkinManager.GiveColor(parts[1])
  149. elif len(parts) == 3:
  150. if parts[1] != "None":
  151. Color = MySkinManager.GiveColor(parts[1])
  152. if parts[2] != "None":
  153. Font = MyLangManager.TrFont(parts[2])
  154. elif len(parts) == 4:
  155. if parts[1] != "None":
  156. Color = MySkinManager.GiveColor(parts[1])
  157. if parts[2] != "None":
  158. Font = MyLangManager.TrFont(parts[2])
  159. if parts[3] == "True":
  160. Bold = True
  161. elif len(parts) == 5:
  162. if parts[1] != "None":
  163. Color = MySkinManager.GiveColor(parts[1])
  164. if parts[2] != "None":
  165. Font = MyLangManager.TrFont(parts[2])
  166. if parts[3] == "True":
  167. Bold = True
  168. if parts[4] == "True":
  169. Und = True
  170. a = Text(Txt,Color,Font,Bold,Und)
  171. d = d + a.Words()
  172. self._Board.SetAndBlitText(d)
  173. else:
  174. a = Text("MD5 check Failed!\n",None,MyLangManager.TrFont("varela16"))
  175. b = Text("Do you want to continue?",None,MyLangManager.TrFont("varela16"))
  176. self._Board.SetAndBlitText(a.Words()+b.Words())
  177. def KeyDown(self,event):
  178. if IsKeyMenuOrB(event.key):
  179. self.ReturnToUpLevelPage()
  180. self._Screen.Draw()
  181. self._Screen.SwapAndShow()
  182. return
  183. if IsKeyStartOrA(event.key):
  184. self._Leader.InstallPackage(self._Screen)
  185. return
  186. def OnLoadCb(self):
  187. pass
  188. def Draw(self):
  189. self.ClearCanvas()
  190. if self._BGpng != None:
  191. self._BGpng.NewCoord((self._Width-self._BGpng._Width)/2,self._Padding.y)
  192. self._BGpng.DrawTopLeft()
  193. self._Board._PosY = self._BGpng._Height+self._Padding.y+self._Padding.h
  194. else:
  195. self._Board._PosY = self._Padding.y
  196. self._Board.Draw()
  197. class MyCommercialSoftwarePackage(object):
  198. _ComPkgInfo = None
  199. _Done = ""
  200. _InvokeDir = ""
  201. def __init__(self):
  202. pass
  203. def CheckPackage(self,main_screen):##detect zip files
  204. ret = False
  205. json_config = self._ComPkgInfo
  206. if not json_config:
  207. return ret
  208. cur_dir = os.getcwd()
  209. if FileExists(json_config["GameDir"]):
  210. os.chdir(json_config["GameDir"])
  211. else:
  212. os.system( "mkdir %s" % json_config["GameDir"] )
  213. if "MD5" in json_config:
  214. for i,v in enumerate(json_config["MD5"]):
  215. if FileExists(v):
  216. ret = True
  217. break
  218. os.chdir(cur_dir)
  219. return ret
  220. def InstallPackage(self,main_screen):
  221. main_screen._MsgBox.SetText("Installing the package")
  222. main_screen._MsgBox.Draw()
  223. main_screen.SwapAndShow()
  224. json_config = self._ComPkgInfo
  225. cur_dir = os.getcwd()
  226. os.chdir(json_config["GameDir"])
  227. for i,v in enumerate(json_config["MD5"]):
  228. if FileExists(v):
  229. os.system("unzip -o %s" %v) ## auto overwrite
  230. if "Post-Up" in json_config:
  231. if FileExists(self._InvokeDir):
  232. os.chdir(self._InvokeDir)
  233. os.system(json_config["Post-Up"])
  234. os.chdir(cur_dir)
  235. pygame.time.delay(1000)
  236. main_screen._MsgBox.SetText("Package Installed")
  237. main_screen._MsgBox.Draw()
  238. main_screen.SwapAndShow()
  239. pygame.time.delay(500)
  240. pygame.event.post( pygame.event.Event(RESTARTUI, message=""))
  241. def VerifyPackage(self,main_screen):
  242. ## do unzip and check md5sum once
  243. main_screen._MsgBox.SetText("Verify the package")
  244. main_screen._MsgBox.Draw()
  245. main_screen.SwapAndShow()
  246. pygame.time.delay(400)
  247. Checked = False
  248. json_config = self._ComPkgInfo
  249. if json_config == None:
  250. return
  251. if "MD5" in json_config:
  252. for i,v in enumerate(json_config["MD5"]):
  253. #print(i,v)
  254. if FileExists( os.path.join(json_config["GameDir"], v )):
  255. print( os.path.join(json_config["GameDir"],v ))
  256. out = commands.getstatusoutput("md5sum %s" % os.path.join(json_config["GameDir"],v))
  257. ret = out[1]
  258. ret = ret.split(" ")
  259. print(ret)
  260. if ret[0] == json_config["MD5"][v]:
  261. print("md5 is ok")
  262. Checked = True
  263. return Checked
  264. return Checked
  265. def Init(self,main_screen):
  266. self._Page1 = NotFoundPage()
  267. self._Page1._Name = "Not Found"
  268. self._Page1._Screen = main_screen
  269. self._Page1._Leader = self
  270. self._Page1.Init()
  271. self._Page2 = HashErrPage()
  272. self._Page2._Name = "Md5sum check failed"
  273. self._Page2._Screen = main_screen
  274. self._Page2._Leader = self
  275. self._Page2.Init()
  276. def API(self,main_screen):
  277. if main_screen !=None:
  278. if self._Done != "":
  279. #try to check if the installed package still there, if not ,remove the done flag file
  280. if FileExists(os.path.join(self._ComPkgInfo["GameDir"],self._ComPkgInfo["InstallDir"] )) == False:
  281. done_file = os.path.join( os.path.dirname(self._Done),".done")
  282. if FileExists(done_file):
  283. os.remove(done_file)
  284. main_screen._MsgBox.SetText("Starting")
  285. main_screen._MsgBox.Draw()
  286. main_screen.SwapAndShow()
  287. pygame.time.delay(300)
  288. ####
  289. pygame.event.post( pygame.event.Event(RUNEVT, message=self._Done))
  290. ####
  291. else:
  292. #print(self._ComPkgInfo)
  293. #if FileExists( os.path.join(self._ComPkgInfo["GameDir"],self._ComPkgInfo["InstallDir"] )) == False:
  294. if self.CheckPackage(main_screen) == False:
  295. main_screen.PushPage(self._Page1)
  296. main_screen.Draw()
  297. main_screen.SwapAndShow()
  298. else:
  299. if self.VerifyPackage(main_screen) == False:
  300. main_screen.PushPage(self._Page2)
  301. main_screen.Draw()
  302. main_screen.SwapAndShow()
  303. else:
  304. self.InstallPackage(main_screen)