Advertisement
cracker64

TPT Script Manager

Aug 2nd, 2012
5,297
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 39.16 KB | None | 0 0
  1. --Cracker64's Autorun Script Manager
  2. --The autorun to end all autoruns
  3. --Version 3.0
  4.  
  5. --TODO:
  6. --manual file addition (that can be anywhere and any extension)
  7. --Moving window (because why not)
  8. --some more API functions
  9. --prettier, organize code
  10.  
  11. --CHANGES:
  12. --central script / update server at starcatcher.us / delete local scripts / lots of other things by jacob1 v3.0
  13. --Scan all subdirectories in scripts folder! v2.25
  14. --Remove step hooks, v87 fixes them
  15. --Socket is now default in v87+ , horray, everyone can now use update features without extra downloads.
  16. --Handles up to 50 extra step functions, up from the default 5 (not including the manager's step) v2.1
  17. --Other various nice API functions
  18. --Scripts can store/retrieve settings through the manager, see comments below v2.0
  19. --Small fillrect change for v85, boxes can have backgrounds v1.92
  20. --Support spaces in exe names v1.91
  21. --Auto-update for OTHER scripts now works, is a bit messy, will fix later, but nothing should change for users to use this
  22. --  Place a line '--VER num UPDATE link' in one of the first four lines of the file, see my above example
  23. --  The link at top downloads a file that contains ONLY version,full link,and prints the rest(changelog). See my link for example
  24.  
  25. if not socket then error("TPT version not supported") end
  26.  
  27. local VERSION = "3.0"
  28. local scriptversion = 1
  29. local TPT_LUA_PATH = 'scripts'
  30. local PATH_SEP = '\\'
  31. local WINDOWS=true
  32. local EXE_NAME = "Powder.exe"
  33. local CHECKUPDATE = false
  34. if os.getenv('HOME') then
  35.     PATH_SEP = '/'
  36.     EXE_NAME = "powder"
  37.     WINDOWS=false
  38. end
  39. local filenames = {}
  40. local num_files = 0 --downloaded scripts aren't stored in filenames
  41. local localscripts = {}
  42. local onlinescripts = {}
  43. local running = {}
  44. local requiresrestart=false
  45. local hidden_mode=true
  46. local online = false
  47. local first_online = true
  48. local updatetable --temporarily holds info on script manager updates
  49. local gen_buttons
  50. local sidebutton
  51. local download_file
  52. local settings = {}
  53. math.randomseed(os.time()) math.random() math.random() math.random() --some filler randoms
  54.  
  55. --get line that can be saved into scriptinfo file
  56. local function scriptInfoString(info)
  57.     --Write table into data format
  58.     if type(info)~="table" then return end
  59.     local t = {}
  60.     for k,v in pairs(info) do
  61.         table.insert(t,k..":\""..v.."\"")
  62.     end
  63.     local rstr = table.concat(t,","):gsub("\n","\\n")
  64.     return rstr
  65. end
  66.  
  67. --read a scriptinfo line
  68. local function readScriptInfo(list)
  69.     if not list then return {} end
  70.     local scriptlist = {}
  71.     for i in list:gmatch("[^\n]+") do
  72.         local t = {}
  73.         local ID = 0
  74.         for k,v in i:gmatch("(%w+):\"([^\"]*)\"") do
  75.             t[k]= tonumber(v) or v:gsub("\\n","\n")
  76.         end
  77.         scriptlist[t.ID] = t
  78.     end
  79.     return scriptlist
  80. end
  81.  
  82. --save settings
  83. local function save_last()
  84.     local savestring=""
  85.     for script,v in pairs(running) do
  86.         savestring = savestring.." \'"..script.."\'"
  87.     end
  88.     savestring = "SAV "..savestring.."\nEXE "..EXE_NAME.."\nDIR "..TPT_LUA_PATH
  89.     for k,t in pairs(settings) do
  90.     for n,v in pairs(t) do
  91.         savestring = savestring.."\nSET "..k.." "..n..":'"..v.."'"     
  92.     end
  93.     end
  94.     local f
  95.     if TPT_LUA_PATH == "scripts" then
  96.         f = io.open(TPT_LUA_PATH..PATH_SEP.."autorunsettings.txt", "w")
  97.     else
  98.         f = io.open("autorunsettings.txt", "w")
  99.     end
  100.     if f then
  101.         f:write(savestring)
  102.         f:close()
  103.     end
  104.  
  105.     f = io.open(TPT_LUA_PATH..PATH_SEP.."downloaded"..PATH_SEP.."scriptinfo", "w")
  106.     if f then
  107.         for k,v in pairs(localscripts) do
  108.             f:write(scriptInfoString(v).."\n")
  109.         end
  110.         f:close()
  111.     end
  112. end
  113.  
  114. --load settings before anything else
  115. local function load_last()
  116.     local f = io.open(TPT_LUA_PATH..PATH_SEP.."autorunsettings.txt","r")
  117.     if not f then
  118.         f = io.open("autorunsettings.txt","r")
  119.     end
  120.     if f then
  121.         local lines = {}
  122.         local line = f:read("*l")
  123.         while line do
  124.             table.insert(lines,line)
  125.             line = f:read("*l")
  126.         end
  127.         f:close()
  128.         for i=1, #lines do
  129.             local tok=lines[i]:sub(1,3)
  130.             local str=lines[i]:sub(5)
  131.             if tok=="SAV" then
  132.                 for word in string.gmatch(str, "\'(.-)\'") do running[word] = true end
  133.             elseif tok=="EXE" then
  134.                 EXE_NAME=str
  135.             elseif tok=="DIR" then
  136.                 TPT_LUA_PATH=str
  137.             elseif tok=="SET" then
  138.             local ident,name,val = string.match(str,"(.-) (.-):\'(.-)\'")
  139.         if settings[ident] then settings[ident][name]=val
  140.         else settings[ident]={[name]=val} end
  141.             end
  142.         end
  143.     end
  144.  
  145.     f = io.open(TPT_LUA_PATH..PATH_SEP.."downloaded"..PATH_SEP.."scriptinfo","r")
  146.     if f then
  147.         local lines = f:read("*a")
  148.         f:close()
  149.         localscripts = readScriptInfo(lines)
  150.         for k,v in pairs(localscripts) do
  151.             if k ~= 1 then
  152.                 if not v["ID"] or not v["name"] or not v["description"] or not v["path"] or not v["version"] then
  153.                     localscripts[k] = nil
  154.                 elseif not fs.exists(TPT_LUA_PATH.."/"..v["path"]:gsub("\\","/")) then
  155.                      localscripts[k] = nil
  156.                 end
  157.             end
  158.         end
  159.     end
  160. end
  161. load_last()
  162. --get list of files in scripts folder
  163. local function load_filenames()
  164.     filenames = {}
  165.     local function searchRecursive(directory)
  166.         local dirlist = fs.list(directory)
  167.         if not dirlist then return end
  168.         for i,v in ipairs(dirlist) do
  169.             local file = directory.."/"..v
  170.             if fs.isDirectory(file) and v ~= "downloaded" then
  171.                 searchRecursive(file)
  172.             elseif fs.isFile(file) then
  173.                 if file:find("%.lua$") then
  174.                     local toinsert = file:sub(#TPT_LUA_PATH+2)
  175.                     if WINDOWS then
  176.                         toinsert = toinsert:gsub("/", "\\") --not actually required
  177.                     end
  178.                     table.insert(filenames, toinsert)
  179.                 end
  180.             end
  181.         end
  182.     end
  183.     searchRecursive(TPT_LUA_PATH)
  184. end
  185. --ui object stuff
  186. local ui_base local ui_box local ui_line local ui_text local ui_button local ui_scrollbar local ui_tooltip local ui_checkbox local ui_console local ui_window
  187. local tooltip
  188. ui_base = {
  189. new = function()
  190.     local b={}
  191.     b.drawlist = {}
  192.     function b:drawadd(f)
  193.         table.insert(self.drawlist,f)
  194.     end
  195.     function b:draw(...)
  196.         for _,f in ipairs(self.drawlist) do
  197.             if type(f)=="function" then
  198.                 f(self,unpack(arg))
  199.             end
  200.         end
  201.     end
  202.     b.movelist = {}
  203.     function b:moveadd(f)
  204.         table.insert(self.movelist,f)
  205.     end
  206.     function b:onmove(x,y)
  207.         for _,f in ipairs(self.movelist) do
  208.             if type(f)=="function" then
  209.                 f(self,x,y)
  210.             end
  211.         end
  212.     end
  213.     return b
  214. end
  215. }
  216. ui_box = {
  217. new = function(x,y,w,h,r,g,b)
  218.     local box=ui_base.new()
  219.     box.x=x box.y=y box.w=w box.h=h box.x2=x+w box.y2=y+h
  220.     box.r=r or 255 box.g=g or 255 box.b=b or 255
  221.     function box:setcolor(r,g,b) self.r=r self.g=g self.b=b end
  222.     function box:setbackground(r,g,b,a) self.br=r self.bg=g self.bb=b self.ba=a end
  223.     box.drawbox=true
  224.     box.drawbackground=false
  225.     box:drawadd(function(self) if self.drawbackground then tpt.fillrect(self.x,self.y,self.w+1,self.h+1,self.br,self.bg,self.bb,self.ba) end
  226.                                 if self.drawbox then tpt.drawrect(self.x,self.y,self.w,self.h,self.r,self.g,self.b) end end)
  227.     box:moveadd(function(self,x,y)
  228.         if x then self.x=self.x+x self.x2=self.x2+x end
  229.         if y then self.y=self.y+y self.y2=self.y2+y end
  230.     end)
  231.     return box
  232. end
  233. }
  234. ui_line = {
  235. new=function(x,y,x2,y2,r,g,b)
  236.     local line=ui_box.new(x,y,x2-x,y2-y,r,g,b)
  237.     --Line is essentially a box, but with a different draw
  238.     line.drawlist={}
  239.     line:drawadd(function(self) tpt.drawline(self.x,self.y,self.x2,self.y2,self.r,self.g,self.b) end)
  240.     return line
  241.     end
  242. }
  243. ui_text = {
  244. new = function(text,x,y,r,g,b)
  245.     local txt = ui_base.new()
  246.     txt.text = text
  247.     txt.x=x or 0 txt.y=y or 0 txt.r=r or 255 txt.g=g or 255 txt.b=b or 255
  248.     function txt:setcolor(r,g,b) self.r=r self.g=g self.b=b end
  249.     txt:drawadd(function(self,x,y) tpt.drawtext(x or self.x,y or self.y,self.text,self.r,self.g,self.b) end)
  250.     txt:moveadd(function(self,x,y)
  251.         if x then self.x=self.x+x end
  252.         if y then self.y=self.y+y end  
  253.     end)
  254.     function txt:process() return false end
  255.     return txt
  256. end,
  257. --Scrolls while holding mouse over
  258. newscroll = function(text,x,y,vis,r,g,b)
  259.     local txt = ui_text.new(text,x,y,r,g,b)
  260.     if tpt.textwidth(text)<vis then return txt end
  261.     txt.visible=vis
  262.     txt.length=string.len(text)
  263.     txt.start=1
  264.     txt.drawlist={} --reset draw
  265.     txt.timer=socket.gettime()+3
  266.     function txt:cuttext(self)
  267.         local last = self.start+1
  268.         while tpt.textwidth(self.text:sub(self.start,last))<txt.visible and last<=self.length do
  269.             last = last+1
  270.         end
  271.         self.last=last-1
  272.     end
  273.     txt:cuttext(txt)
  274.     txt.minlast=txt.last-1
  275.     txt.ppl=((txt.visible-6)/(txt.length-txt.minlast+1))
  276.     txt:drawadd(function(self,x,y)
  277.         if socket.gettime() > self.timer then
  278.             if self.last >= self.length then
  279.                 self.start = 1
  280.                 self:cuttext(self)
  281.                 self.timer = socket.gettime()+3
  282.             else
  283.                 self.start = self.start + 1
  284.                 self:cuttext(self)
  285.                 if self.last >= self.length then
  286.                     self.timer = socket.gettime()+3
  287.                 else
  288.                     self.timer = socket.gettime()+.15
  289.                 end
  290.             end
  291.         end
  292.         tpt.drawtext(x or self.x,y or self.y, self.text:sub(self.start,self.last) ,self.r,self.g,self.b)
  293.     end)
  294.     function txt:process(mx,my,button,event,wheel)
  295.         if event==3 then
  296.             local newlast = math.floor((mx-self.x)/self.ppl)+self.minlast
  297.             if newlast<self.minlast then newlast=self.minlast end
  298.             if newlast>0 and newlast~=self.last then
  299.                 local newstart=1
  300.                 while tpt.textwidth(self.text:sub(newstart,newlast))>= self.visible do
  301.                     newstart=newstart+1
  302.                 end
  303.                 self.start=newstart self.last=newlast
  304.                 self.timer = socket.gettime()+3
  305.             end
  306.         end
  307.     end
  308.     return txt
  309. end
  310. }
  311. ui_scrollbar = {
  312. new = function(x,y,h,t,m)
  313.     local bar = ui_base.new() --use line object as base?
  314.     bar.x=x bar.y=y bar.h=h
  315.     bar.total=t
  316.     bar.numshown=m
  317.     bar.pos=0
  318.     bar.length=math.floor((1/math.ceil(bar.total-bar.numshown+1))*bar.h)
  319.     bar.soffset=math.floor(bar.pos*((bar.h-bar.length)/(bar.total-bar.numshown)))
  320.     function bar:update(total,shown,pos)
  321.         self.pos=pos or 0
  322.         if self.pos<0 then self.pos=0 end
  323.         self.total=total
  324.         self.numshown=shown
  325.         self.length= math.floor((1/math.ceil(self.total-self.numshown+1))*self.h)
  326.         self.soffset= math.floor(self.pos*((self.h-self.length)/(self.total-self.numshown)))
  327.     end
  328.     function bar:move(wheel)
  329.         self.pos = self.pos-wheel
  330.         if self.pos < 0 then self.pos=0 end
  331.         if self.pos > (self.total-self.numshown) then self.pos=(self.total-self.numshown) end
  332.         self.soffset= math.floor(self.pos*((self.h-self.length)/(self.total-self.numshown)))
  333.     end
  334.     bar:drawadd(function(self)
  335.         if self.total > self.numshown then
  336.             tpt.drawline(self.x,self.y+self.soffset,self.x,self.y+self.soffset+self.length)
  337.         end
  338.     end)
  339.     bar:moveadd(function(self,x,y)
  340.         if x then self.x=self.x+x end
  341.         if y then self.y=self.y+y end  
  342.     end)
  343.     function bar:process(mx,my,button,event,wheel)
  344.         if wheel~=0 and not hidden_mode then
  345.             if self.total > self.numshown then
  346.                 local previous = self.pos
  347.                 self:move(wheel)
  348.                 if self.pos~=previous then
  349.                     return wheel
  350.                 end
  351.             end
  352.         end
  353.         --possibly click the bar and drag?
  354.         return false
  355.     end
  356.     return bar
  357. end
  358. }
  359. ui_button = {
  360. new = function(x,y,w,h,f,text)
  361.     local b = ui_box.new(x,y,w,h)
  362.     b.f=f
  363.     b.t=ui_text.new(text,x+2,y+2)
  364.     b.drawbox=false
  365.     b.almostselected=false
  366.     b.invert=true
  367.     b:setbackground(127,127,127,125)
  368.     b:drawadd(function(self)
  369.         if self.invert and self.almostselected then
  370.             self.almostselected=false
  371.             tpt.fillrect(self.x,self.y,self.w,self.h)
  372.             local tr=self.t.r local tg=self.t.g local tb=self.t.b
  373.             b.t:setcolor(0,0,0)
  374.             b.t:draw()
  375.             b.t:setcolor(tr,tg,tb)
  376.         else
  377.             if tpt.mousex>=self.x and tpt.mousex<=self.x2 and tpt.mousey>=self.y and tpt.mousey<=self.y2 then
  378.                 self.drawbackground=true
  379.             else
  380.                 self.drawbackground=false
  381.             end
  382.             b.t:draw()
  383.         end
  384.     end)
  385.     b:moveadd(function(self,x,y)
  386.         self.t:onmove(x,y)
  387.     end)
  388.     function b:process(mx,my,button,event,wheel)
  389.         if mx<self.x or mx>self.x2 or my<self.y or my>self.y2 then return false end
  390.         if event==3 then self.almostselected=true end
  391.         if event==2 then self:f() end
  392.         return true
  393.     end
  394.     return b
  395. end
  396. }
  397. ui_tooltip = {
  398. new = function(x,y,w,text)
  399.     local b = ui_box.new(x,y-1,w,0)
  400.     function b:updatetooltip(tooltip)
  401.         self.tooltip = tooltip
  402.         self.length = #tooltip
  403.         self.lines = 0
  404.         local start,last = 1,2
  405.         while last <= self.length do
  406.             while tpt.textwidth(self.tooltip:sub(start,last)) < w and last <= self.length and self.tooltip:sub(last,last) ~= '\n' do
  407.                 last = last + 1
  408.             end
  409.             if last <= self.length and self.tooltip:sub(last,last) ~= '\n' then
  410.                 self.length = self.length + 1
  411.                 self.tooltip = self.tooltip:sub(1,last-1).."\n"..self.tooltip:sub(last)
  412.             end
  413.             last = last + 1
  414.             start = last
  415.             self.lines = self.lines + 1
  416.         end
  417.         self.h = self.lines*12+2
  418.         --if self.lines == 1 then self.w = tpt.textwidth(self.tooltip)+3 end
  419.         self.drawbox = tooltip ~= ""
  420.         self.drawbackground = tooltip ~= ""
  421.     end
  422.     function b:settooltip(tooltip_)
  423.         tooltip:onmove(tpt.mousex-tooltip.x, tpt.mousey-tooltip.y)
  424.         tooltip:updatetooltip(tooltip_)
  425.     end
  426.     b:updatetooltip(text)
  427.     b:setbackground(0,0,0,255)
  428.     b.drawbackground = true
  429.     b:drawadd(function(self)
  430.         if self.tooltip ~= "" then
  431.             tpt.drawtext(self.x+1,self.y+2,self.tooltip)
  432.         end
  433.         self:updatetooltip("")
  434.     end)
  435.     function b:process(mx,my,button,event,wheel) end
  436.     return b
  437. end
  438. }
  439. ui_checkbox = {
  440. up_button = function(x,y,w,h,f,text)
  441.     local b=ui_button.new(x,y,w,h,f,text)
  442.     b.canupdate=false
  443.     return b
  444. end,
  445. new_button = function(x,y,w,h,splitx,f,f2,text)
  446.     local b = ui_box.new(x,y,splitx,h)
  447.     b.f=f b.f2=f2
  448.     b.splitx = splitx
  449.     b.t=ui_text.newscroll(text,x+24,y+2,splitx-24)
  450.     b.selected=false
  451.     b.checkbut=ui_checkbox.up_button(x+splitx+9,y,33,10,ui_button.scriptcheck,"Update")
  452.     b.canupdate = false
  453.     b.drawbox=false
  454.     b:setbackground(127,127,127,100)
  455.     b:drawadd(function(self)
  456.         if tpt.mousex>=self.x and tpt.mousex<self.x2 and tpt.mousey>=self.y and tpt.mousey<self.y2 then
  457.             local script
  458.             if online and onlinescripts[self.ID]["description"] then
  459.                 script = onlinescripts[self.ID]
  460.             elseif not online and localscripts[self.ID] then
  461.                 script = localscripts[self.ID]
  462.             end
  463.             if script then
  464.                 tooltip:settooltip(script["name"].." by "..script["author"].."\n\n"..script["description"])
  465.             end
  466.             self.drawbackground=true
  467.         else
  468.             if tpt.mousey>=self.y and tpt.mousey<self.y2 then
  469.                 if tpt.mousex < self.x2+10 and self.running then
  470.                     tooltip:settooltip(online and "downloaded" or "running")
  471.                 elseif tpt.mousex > self.x2+33 and onlinescripts[self.ID] and onlinescripts[self.ID]["changelog"] then
  472.                     tooltip:settooltip(onlinescripts[self.ID]["changelog"])
  473.                 end
  474.             end
  475.             self.drawbackground=false
  476.         end
  477.         self.t:draw()
  478.         if self.f2 then
  479.             if self.deletealmostselected then
  480.                 self.deletealmostselected = false
  481.                 tpt.drawtext(self.x+1, self.y+1, "\134", 255, 48, 32, 255)
  482.             else
  483.                 tpt.drawtext(self.x+1, self.y+1, "\134", 160, 48, 32, 255)
  484.             end
  485.             tpt.drawtext(self.x+1, self.y+1, "\133", 255, 255, 255, 255)
  486.         end
  487.         tpt.drawrect(self.x+12,self.y+1,8,8)
  488.         if self.almostselected then self.almostselected=false tpt.fillrect(self.x+12,self.y+1,8,8,150,150,150)
  489.         elseif self.selected then tpt.fillrect(self.x+12,self.y+1,8,8) end
  490.         local filepath = self.ID and localscripts[self.ID] and localscripts[self.ID]["path"] or self.t.text
  491.         if self.running then tpt.drawtext(self.x+self.splitx+2,self.y+2,online and "D" or "R") end
  492.         if self.checkbut.canupdate then self.checkbut:draw() end
  493.     end)
  494.     b:moveadd(function(self,x,y)
  495.         self.t:onmove(x,y)
  496.         self.checkbut:onmove(x,y)
  497.     end)
  498.     function b:process(mx,my,button,event,wheel)
  499.         if self.f2 and mx <= self.x+8 then
  500.             if event==3 then self.deletealmostselected = true end
  501.             if event==2 then self:f2() end
  502.         elseif mx<=self.x+self.splitx then
  503.             if event==3 then self.almostselected=true end
  504.             if event==2 then self:f() end
  505.             self.t:process(mx,my,button,event,wheel)
  506.         else
  507.             if self.checkbut.canupdate then self.checkbut:process(mx,my,button,event,wheel) end
  508.         end
  509.         return true
  510.     end
  511.     return b
  512. end,
  513. new = function(x,y,w,h)
  514.     local box = ui_box.new(x,y,w,h)
  515.     box.list={}
  516.     box.numlist = 0
  517.     box.max_lines = math.floor(box.h/10)-1
  518.     box.max_text_width = math.floor(box.w*0.8)
  519.     box.splitx=x+box.max_text_width
  520.     box.scrollbar = ui_scrollbar.new(box.x2-2,box.y+11,box.h-12,0,box.max_lines)
  521.     box.lines={
  522.         ui_line.new(box.x+1,box.y+10,box.x2-1,box.y+10,170,170,170),
  523.         ui_line.new(box.x+22,box.y+10,box.x+22,box.y2-1,170,170,170),
  524.         ui_line.new(box.splitx,box.y+10,box.splitx,box.y2-1,170,170,170),
  525.         ui_line.new(box.splitx+9,box.y+10,box.splitx+9,box.y2-1,170,170,170),
  526.     }
  527.     function box:updatescroll()
  528.         self.scrollbar:update(self.numlist,self.max_lines)
  529.     end
  530.     function box:clear()
  531.         self.list={}
  532.         self.numlist=0
  533.     end
  534.     function box:add(f,f2,text)
  535.         local but = ui_checkbox.new_button(self.x,self.y+1+((self.numlist+1)*10),tpt.textwidth(text)+4,10,self.max_text_width,f,f2,text)
  536.         table.insert(self.list,but)
  537.         self.numlist = #self.list
  538.         return but
  539.     end
  540.     box:drawadd(function (self)
  541.         tpt.drawtext(self.x+24,self.y+2,"Files in "..TPT_LUA_PATH.." folder")
  542.         tpt.drawtext(self.splitx+11,self.y+2,"Update")
  543.         for i,line in ipairs(self.lines) do
  544.             line:draw()
  545.         end
  546.         self.scrollbar:draw()
  547.         local restart = false
  548.         for i,check in ipairs(self.list) do
  549.             local filepath = check.ID and localscripts[check.ID] and localscripts[check.ID]["path"] or check.t.text
  550.             if not check.selected and running[filepath] then
  551.                 restart = true
  552.             end
  553.             if i>self.scrollbar.pos and i<=self.scrollbar.pos+self.max_lines then
  554.                 check:draw()
  555.             end
  556.         end
  557.         requiresrestart = restart and not online
  558.     end)
  559.     box:moveadd(function(self,x,y)
  560.         for i,line in ipairs(self.lines) do
  561.             line:onmove(x,y)
  562.         end
  563.         for i,check in ipairs(self.list) do
  564.             check:onmove(x,y)
  565.         end
  566.     end)
  567.     function box:scroll(amount)
  568.         local move = amount*10
  569.         if move==0 then return end
  570.         for i,check in ipairs(self.list) do
  571.             check:onmove(0,move)
  572.         end
  573.     end
  574.     function box:process(mx,my,button,event,wheel)
  575.         if mx<self.x or mx>self.x2 or my<self.y or my>self.y2 then return false end
  576.         local scrolled = self.scrollbar:process(mx,my,button,event,wheel)
  577.         if scrolled then self:scroll(scrolled) end
  578.         local which = math.floor((my-self.y-11)/10)+1
  579.         if which>0 and which<=self.numlist then self.list[which+self.scrollbar.pos]:process(mx,my,button,event,wheel) end
  580.         return true
  581.     end
  582.     return box
  583. end
  584. }
  585. ui_console = {
  586. new = function(x,y,w,h)
  587.     local con = ui_box.new(x,y,w,h)
  588.     con.shown_lines = math.floor(con.h/10)
  589.     con.max_lines = 300
  590.     con.max_width = con.w-4
  591.     con.lines = {}
  592.     con.scrollbar = ui_scrollbar.new(con.x2-2,con.y+1,con.h-2,0,con.shown_lines)
  593.     con:drawadd(function(self)
  594.         self.scrollbar:draw()
  595.         local count=0
  596.         for i,line in ipairs(self.lines) do
  597.             if i>self.scrollbar.pos and i<= self.scrollbar.pos+self.shown_lines then
  598.                 line:draw(self.x+3,self.y+3+(count*10))
  599.                 count = count+1
  600.             end
  601.         end
  602.     end)
  603.     con:moveadd(function(self,x,y)
  604.         self.scrollbar:onmove(x,y)
  605.     end)
  606.     function con:clear()
  607.         self.lines = {}
  608.         self.scrollbar:update(0,con.shown_lines)
  609.     end
  610.     function con:addstr(str,r,g,b)
  611.         str = tostring(str)
  612.         local nextl = str:find('\n')
  613.         while nextl do
  614.             local line = str:sub(1,nextl-1)
  615.             self:addline(line,r,g,b)
  616.             str = str:sub(nextl+1)
  617.             nextl = str:find('\n')
  618.         end
  619.         self:addline(str,r,g,b) --anything leftover
  620.     end
  621.     function con:addline(line,r,g,b)
  622.         if not line or line=="" then return end --No blank lines
  623.         table.insert(self.lines,ui_text.newscroll(line,self.x,0,self.max_width,r,g,b))
  624.         if #self.lines>self.max_lines then table.remove(self.lines,1) end
  625.         self.scrollbar:update(#self.lines,self.shown_lines,#self.lines-self.shown_lines)
  626.     end
  627.     function con:process(mx,my,button,event,wheel)
  628.         if mx<self.x or mx>self.x2 or my<self.y or my>self.y2 then return false end
  629.         self.scrollbar:process(mx,my,button,event,wheel)
  630.         local which = math.floor((my-self.y-1)/10)+1
  631.         if which>0 and which<=self.shown_lines and self.lines[which+self.scrollbar.pos] then self.lines[which+self.scrollbar.pos]:process(mx,my,button,event,wheel) end
  632.         return true
  633.     end
  634.     return con
  635. end
  636. }
  637. ui_window = {
  638. new = function(x,y,w,h)
  639.     local w=ui_box.new(x,y,w,h)
  640.     w.sub={}
  641.     function w:add(m,name)
  642.         if name then w[name]=m end
  643.         table.insert(self.sub,m)
  644.     end
  645.     w:drawadd(function(self)
  646.         for i,sub in ipairs(self.sub) do
  647.             sub:draw()
  648.         end
  649.     end)
  650.     w:moveadd(function(self,x,y)
  651.         for i,sub in ipairs(self.sub) do
  652.             sub:onmove(x,y)
  653.         end
  654.     end)
  655.     function w:process(mx,my,button,event,wheel)
  656.         if mx<self.x or mx>self.x2 or my<self.y or my>self.y2 then return false end
  657.         local ret
  658.         for i,sub in ipairs(self.sub) do
  659.             if sub:process(mx,my,button,event,wheel) then ret = true end
  660.         end
  661.         return ret
  662.     end
  663.     return w
  664. end
  665. }
  666. --Main window with everything!
  667. local mainwindow = ui_window.new(50,50,525,300)
  668. mainwindow:setbackground(10,10,10,235) mainwindow.drawbackground=true
  669. mainwindow:add(ui_console.new(275,148,300,189),"menuconsole")
  670. mainwindow:add(ui_checkbox.new(50,80,225,257),"checkbox")
  671. tooltip = ui_tooltip.new(0,1,250,"")
  672.  
  673. --Some API functions you can call from other scripts
  674. --put 'using_manager=MANAGER_EXISTS' or similar in your scripts, using_manager will be true if the manager is active
  675. MANAGER_EXISTS = true
  676. --Print a message to the manager console, can be colored
  677. function MANAGER_PRINT(msg,...)
  678.     mainwindow.menuconsole:addstr(msg,unpack(arg))
  679. end
  680. --send version, for some compatibility
  681. function MANAGER_VERSION()
  682.     return VERSION
  683. end
  684. --downloads and returns a file, so you can do whatever...
  685. function MANAGER_DOWNLOAD(url)
  686.     return download_file(url)
  687. end
  688. --Get various info about the system (if on windows, script directory, path seperator, if socket is loaded)
  689. function MANAGER_SYSINFO()
  690.     return {["isWindows"]=WINDOWS,["scriptDir"]=TPT_LUA_PATH,["pathSep"]=PATH_SEP,["socket"]=true}
  691. end
  692. --Get whether or not the manager window is hidden or not
  693. function MANAGER_HIDDEN()
  694.     return hidden_mode
  695. end
  696. --Save a setting in the autorun settings file, ident should be your script name no one else would use.
  697. --Name is variable name, val is the value which will be saved/returned as a string
  698. function MANAGER_SAVESETTING(ident,name,val)
  699.     ident = tostring(ident)
  700.     name = tostring(name)
  701.     val = tostring(val)
  702.     if settings[ident] then settings[ident][name]=val
  703.     else settings[ident]={[name]=val} end
  704.     save_last()
  705. end
  706. --Get a previously saved value, if it has one
  707. function MANAGER_GETSETTING(ident,name)
  708.     if settings[ident] then return settings[ident][name] end
  709.     return nil
  710. end
  711. --delete a setting, leave name nil to delete all of ident
  712. function MANAGER_DELSETTING(ident,name)
  713.     if settings[ident] then
  714.     if name then settings[ident][name]=nil
  715.     else settings[ident]=nil end
  716.     save_last()
  717.     end
  718. end
  719. --some other API functions here..
  720.  
  721. --mniip's download thing (mostly)
  722. local pattern = "http://w*%.?(.-)(/.*)"
  723. local function download_file(url)
  724.     local _,_,host,rest = url:find(pattern)
  725.     if not host or not rest then MANAGER_PRINT("Bad link") return end
  726.     local conn=socket.tcp()
  727.     if not conn then return end
  728.     local succ=pcall(conn.connect,conn,host,80)
  729.     conn:settimeout(5)
  730.     if not succ then return end
  731.     succ,resp,something=pcall(conn.send,conn,"GET "..rest.." HTTP/1.1\r\nHost: "..host.."\r\nConnection: close\r\n\n")
  732.     if not succ then return end
  733.     local data=""
  734.     local c=""
  735.     while c do
  736.         c=conn:receive("*l")
  737.         if c then
  738.             data=data.."\n"..c
  739.         end
  740.     end
  741.     if data=="" then MANAGER_PRINT("no data") return end
  742.     local first,last,code = data:find("HTTP/1%.1 (.-) .-\n")
  743.     while last do
  744.         data = data:sub(last+1)
  745.         first,last,header = data:find("^([^\n]-:.-)\n")
  746.         --read something from headers?
  747.         if header then
  748.             if tonumber(code)==302 then
  749.                 local _,_,new = header:find("^Location: (.*)")
  750.                 if new then return download_file(new) end
  751.             end
  752.         end
  753.     end
  754.     if host:find("pastebin.com") then --pastebin adds some weird numbers
  755.         _,_,data=data:find("\n[^\n]*\n(.*)\n.+\n$")
  756.     end
  757.     return data
  758. end
  759. --Downloads to a location
  760. local function download_script(ID,location)
  761.     local file = download_file("http://starcatcher.us/scripts/main.lua?get="..ID)
  762.     if file then
  763.         f=io.open(location,"w")
  764.         f:write(file)
  765.         f:close()
  766.         return true
  767.     end
  768.     return false
  769. end
  770. --Restart exe (if named correctly)
  771. local function do_restart()
  772.     save_last()
  773.     if WINDOWS then
  774.         os.execute("TASKKILL /IM \""..EXE_NAME.."\" /F &&START .\\\""..EXE_NAME.."\"")
  775.     else
  776.         os.execute("killall -s KILL \""..EXE_NAME.."\" && ./\""..EXE_NAME.."\"")
  777.     end
  778.     MANAGER_PRINT("Restart failed, do you have the exe name right?",255,0,0)
  779. end
  780. --TPT interface
  781. local function step()
  782.     if tpt.version.jacob1s_mod then
  783.         tpt.fillrect(0,0,gfx.WIDTH,gfx.HEIGHT,0,0,0,150)
  784.     else
  785.         tpt.fillrect(-1,-1,gfx.WIDTH,gfx.HEIGHT,0,0,0,150)
  786.     end
  787.     mainwindow:draw()
  788.     tpt.drawtext(280,140,"Console Output:")
  789.     if requiresrestart then
  790.         tpt.drawtext(280,88,"Disabling a script requires a restart for effect!",255,50,50)
  791.     end
  792.     tpt.drawtext(55,55,"Click a script to toggle, hit DONE when finished")
  793.     tpt.drawtext(474,55,"Script Manager v"..VERSION)--479 for simple versions
  794.     tooltip:draw()
  795. end
  796. local function mouseclick(mousex,mousey,button,event,wheel)
  797.     sidebutton:process(mousex,mousey,button,event,wheel)
  798.     if hidden_mode then return true end
  799.    
  800.     if mousex>612 or mousey>384 then return false end
  801.     mainwindow:process(mousex,mousey,button,event,wheel)
  802.     return false
  803. end
  804. local function keypress(key,nkey,modifier,event)
  805.     if nkey==27 then hidden_mode=true return false end
  806.     if not hidden_mode then return false end
  807. end
  808. --small button on right to bring up main menu
  809. local WHITE = {255,255,255,255}
  810. local BLACK = {0,0,0,255}
  811. local sidecoords = {612,134,16,17}
  812. local ICON = math.random(2) --pick a random icon
  813. local lua_letters= {{{615,136,615,141},{615,141,617,141},{619,141,619,145},{619,145,621,145},{621,141,621,145},{623,145,625,145},{623,145,623,149},{624,147,624,147},{625,145,625,149},},
  814.     {{615,137,615,147},{615,148,620,148},{617,137,617,146},{617,146,620,146},{620,137,620,146},{622,137,625,137},{622,137,622,148},{623,142,624,142},{625,137,625,148},}}
  815. local function smallstep()
  816.     tpt.drawrect(613,135,14,15,200,200,200)
  817.     local color=WHITE
  818.     if not hidden_mode then
  819.         step()
  820.         tpt.fillrect(unpack(sidecoords))
  821.         color=BLACK
  822.     end
  823.     for i,dline in ipairs(lua_letters[ICON]) do
  824.         tpt.drawline(dline[1],dline[2],dline[3],dline[4],color[1],color[2],color[3])
  825.     end
  826. end
  827. --button functions on click
  828. function ui_button.reloadpressed(self)
  829.     load_filenames()
  830.     gen_buttons()
  831.     mainwindow.checkbox:updatescroll()
  832.     if num_files == 0 then
  833.         MANAGER_PRINT("No scripts found in '"..TPT_LUA_PATH.."' folder",255,255,0)
  834.         fs.makeDirectory(TPT_LUA_PATH)
  835.     else
  836.         MANAGER_PRINT("Reloaded file list, found "..num_files.." scripts")
  837.     end
  838. end
  839. function ui_button.selectnone(self)
  840.     for i,but in ipairs(mainwindow.checkbox.list) do
  841.         but.selected = false
  842.     end
  843. end
  844. function ui_button.consoleclear(self)
  845.     mainwindow.menuconsole:clear()
  846. end
  847. function ui_button.changeexename(self)
  848.     local last = EXE_NAME
  849.     local new = tpt.input("Change exe name","Enter the exact name of powder toy executable",EXE_NAME,EXE_NAME)
  850.     if new~=last and new~="" then
  851.         MANAGER_PRINT("Executable name changed to "..new,255,255,0)
  852.         EXE_NAME = new
  853.     end
  854.     save_last()
  855. end
  856. function ui_button.changedir(self)
  857.     local last = TPT_LUA_PATH
  858.     local new = tpt.input("Change search directory","Enter the folder where your scripts are",TPT_LUA_PATH,TPT_LUA_PATH)
  859.     if new~=last and new~="" then
  860.         MANAGER_PRINT("Directory changed to "..new,255,255,0)
  861.         TPT_LUA_PATH = new
  862.     end
  863.     ui_button.reloadpressed()
  864.     save_last()
  865. end
  866. function ui_button.uploadscript(self)
  867.     local command = WINDOWS and "start" or "xdg-open"
  868.     os.execute(command.." http://starcatcher.us/scripts/paste.lua")
  869. end
  870. local lastpaused
  871. function ui_button.sidepressed(self)
  872.     hidden_mode = not hidden_mode
  873.     ui_button.localview()
  874.     if not hidden_mode then
  875.         lastpaused = tpt.set_pause()
  876.         tpt.set_pause(1)
  877.         ui_button.reloadpressed()
  878.     else
  879.         tpt.set_pause(lastpaused)
  880.     end
  881. end
  882. local donebutton
  883. function ui_button.donepressed(self)
  884.     hidden_mode = true
  885.     running = {}
  886.     for i,but in ipairs(mainwindow.checkbox.list) do
  887.         if but.selected then
  888.             local filepath = but.ID and localscripts[but.ID]["path"] or but.t.text
  889.             if requiresrestart then
  890.                 running[filepath] = true
  891.             else
  892.                 if not running[filepath] then
  893.                     local status,err = pcall(dofile,TPT_LUA_PATH..PATH_SEP..filepath)
  894.                     if not status then
  895.                         MANAGER_PRINT(err,255,0,0)
  896.                         print(err)
  897.                         but.selected = false
  898.                     else
  899.                         MANAGER_PRINT("Started "..but.t.text)
  900.                         running[filepath] = true
  901.                     end
  902.                 end
  903.             end
  904.         end
  905.     end
  906.     if requiresrestart then do_restart() return end
  907.     save_last()
  908. end
  909. function ui_button.downloadpressed(self)
  910.     for i,but in ipairs(mainwindow.checkbox.list) do
  911.         if but.selected then
  912.             --maybe do better display names later
  913.             local displayName
  914.             local function get_script(butt)
  915.                 local script = download_file("http://starcatcher.us/scripts/main.lua?get="..butt.ID)
  916.                 displayName = "downloaded"..PATH_SEP..butt.ID.." "..onlinescripts[butt.ID].author.."-"..onlinescripts[butt.ID].name..".lua"
  917.                 local name = TPT_LUA_PATH..PATH_SEP..displayName
  918.                 if not fs.exists(TPT_LUA_PATH..PATH_SEP.."downloaded") then
  919.                     fs.makeDirectory(TPT_LUA_PATH..PATH_SEP.."downloaded")
  920.                 end
  921.                 local file = io.open(name, "w")
  922.                 if not file then error("could not open "..name) end
  923.                 file:write(script)
  924.                 file:close()
  925.                 localscripts[butt.ID] = onlinescripts[butt.ID]
  926.                 localscripts[butt.ID]["path"] = displayName
  927.                 dofile(name)
  928.             end
  929.             local status,err = pcall(get_script, but)
  930.             if not status then
  931.                 MANAGER_PRINT(err,255,0,0)
  932.                 print(err)
  933.                 but.selected = false
  934.             else
  935.                 MANAGER_PRINT("Downloaded and started "..but.t.text)
  936.                 running[displayName] = true
  937.             end
  938.         end
  939.     end
  940.     hidden_mode=true
  941.     ui_button.localview()
  942.     save_last()
  943. end
  944.  
  945. function ui_button.pressed(self)
  946.     self.selected = not self.selected
  947. end
  948. function ui_button.delete(self)
  949.     --there is no tpt.confirm() yet
  950.     if tpt.input("Delete File", "Delete "..self.t.text.."?", "yes", "no") == "yes" then
  951.         local filepath = self.ID and localscripts[self.ID]["path"] or self.t.text
  952.         fs.removeFile(TPT_LUA_PATH.."/"..filepath:gsub("\\","/"))
  953.         if running[filepath] then running[filepath] = nil end
  954.         if localscripts[self.ID] then localscripts[self.ID] = nil end
  955.         save_last()
  956.         ui_button.localview()
  957.         load_filenames()
  958.         gen_buttons()
  959.     end
  960. end
  961. function ui_button.scriptcheck(self)
  962.     if download_script(self.ID,TPT_LUA_PATH..PATH_SEP..localscripts[self.ID]["path"]) then
  963.         self.canupdate = false
  964.         localscripts[self.ID]["version"] = onlinescripts[self.ID]["version"]
  965.         if running[localscripts[self.ID]["path"]] then
  966.             do_restart()
  967.         end
  968.     end
  969. end
  970. function ui_button.doupdate(self)
  971.     fileSystem.move("autorun.lua", "autorunold.lua")
  972.     download_script(1, 'autorun.lua')
  973.     localscripts[1] = updatetable[1]
  974.     do_restart()
  975. end
  976. function ui_button.localview(self)
  977.     if online then
  978.         online = false
  979.         gen_buttons()
  980.         donebutton.t.text = "DONE"
  981.         donebutton.w = 29 donebutton.x2 = donebutton.x + donebutton.w
  982.         donebutton.f = ui_button.donepressed
  983.     end
  984. end
  985. function ui_button.onlineview(self)
  986.     if not online then
  987.         online = true
  988.         gen_buttons()
  989.         donebutton.t.text = "DOWNLOAD"
  990.         donebutton.w = 55 donebutton.x2 = donebutton.x + donebutton.w
  991.         donebutton.f = ui_button.downloadpressed
  992.     end
  993. end
  994. --add buttons to window
  995. donebutton = ui_button.new(55,339,29,10,ui_button.donepressed,"DONE")
  996. mainwindow:add(donebutton)
  997. mainwindow:add(ui_button.new(134,339,40,10,ui_button.sidepressed,"CANCEL"))
  998. --mainwindow:add(ui_button.new(152,339,29,10,ui_button.selectnone,"NONE"))
  999. local nonebutton = ui_button.new(62,81,8,8,ui_button.selectnone,"")
  1000. nonebutton.drawbox = true
  1001. mainwindow:add(nonebutton)
  1002. mainwindow:add(ui_button.new(538,339,33,10,ui_button.consoleclear,"CLEAR"))
  1003. mainwindow:add(ui_button.new(278,67,40,10,ui_button.reloadpressed,"RELOAD"))
  1004. mainwindow:add(ui_button.new(333,67,80,10,ui_button.changeexename,"Change exe name"))
  1005. mainwindow:add(ui_button.new(428,67,51,10,ui_button.changedir,"Change dir"))
  1006. mainwindow:add(ui_button.new(493,67,68,10,ui_button.uploadscript,"Upload Script"))
  1007. local tempbutton = ui_button.new(60, 65, 30, 10, ui_button.localview, "Local")
  1008. tempbutton.drawbox = true
  1009. mainwindow:add(tempbutton)
  1010. tempbutton = ui_button.new(100, 65, 35, 10, ui_button.onlineview, "Online")
  1011. tempbutton.drawbox = true
  1012. mainwindow:add(tempbutton)
  1013. sidebutton = ui_button.new(613,134,14,15,ui_button.sidepressed,'')
  1014.  
  1015. local function gen_buttons_local()
  1016.     local count = 0
  1017.     for k,v in pairs(localscripts) do
  1018.         local check = mainwindow.checkbox:add(ui_button.pressed,ui_button.delete,v["name"])
  1019.         check.ID = k
  1020.         if running[v["path"]] then
  1021.             check.running = true
  1022.             check.selected = true
  1023.         end
  1024.         count = count + 1
  1025.     end
  1026.     for i=1,#filenames do
  1027.         local check = mainwindow.checkbox:add(ui_button.pressed,ui_button.delete,filenames[i])
  1028.         if running[filenames[i]] then
  1029.             check.running = true
  1030.             check.selected = true
  1031.         end
  1032.     end
  1033.     num_files = count + #filenames
  1034. end
  1035. local function gen_buttons_online()
  1036.     local list = download_file("http://starcatcher.us/scripts/main.lua")
  1037.     onlinescripts = readScriptInfo(list)
  1038.     for k,v in pairs(onlinescripts) do
  1039.         local check = mainwindow.checkbox:add(ui_button.pressed, nil, v["name"])
  1040.         check.ID = k
  1041.         check.checkbut.ID = k
  1042.         if localscripts[check.ID] then
  1043.             check.running = true
  1044.             if tonumber(v["version"]) > tonumber(localscripts[check.ID]["version"]) then
  1045.                 check.checkbut.canupdate = true
  1046.             end
  1047.         end
  1048.     end
  1049.     if first_online then
  1050.         first_online = false
  1051.         local updateinfo = download_file("http://starcatcher.us/scripts/main.lua?info=1")
  1052.         updatetable = readScriptInfo(updateinfo)
  1053.         if not updatetable[1] then return end
  1054.         if tonumber(updatetable[1].version) > scriptversion then
  1055.             local updatebutton = ui_button.new(278,127,40,10,ui_button.doupdate,"UPDATE")
  1056.             updatebutton.t:setcolor(25,255,25)
  1057.             mainwindow:add(updatebutton)
  1058.             MANAGER_PRINT("A script manager update is available! Click UPDATE",25,255,55)
  1059.             MANAGER_PRINT(updatetable[1].changelog,25,255,55)
  1060.         end
  1061.     end
  1062. end
  1063. gen_buttons = function()
  1064.     mainwindow.checkbox:clear()
  1065.     if online then
  1066.         gen_buttons_online()
  1067.     else
  1068.         gen_buttons_local()
  1069.     end
  1070.     mainwindow.checkbox:updatescroll()
  1071. end
  1072. gen_buttons()
  1073.  
  1074. --register manager first
  1075. tpt.register_step(smallstep)
  1076. --load previously running scripts
  1077. local started = ""
  1078. for prev,v in pairs(running) do
  1079.     local status,err = pcall(dofile,TPT_LUA_PATH..PATH_SEP..prev)
  1080.     if not status then
  1081.         MANAGER_PRINT(err,255,0,0)
  1082.         running[prev] = nil
  1083.     else
  1084.         started=started.." "..prev
  1085.         local newbut = mainwindow.checkbox:add(ui_button.pressed,prev)
  1086.         newbut.selected=true
  1087.     end
  1088. end
  1089. save_last()
  1090. if started~="" then
  1091.     MANAGER_PRINT("Auto started"..started)
  1092. end
  1093. tpt.register_mouseevent(mouseclick)
  1094. tpt.register_keypress(keypress)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement