Orion09

QuartzOS

Mar 16th, 2025 (edited)
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.57 KB | None | 0 0
  1. function scanPeripherals()
  2. term.setTextColor(colors.cyan)
  3. print("Scanning for peripherals...\n")
  4.  
  5. local sides = {"top", "bottom", "left", "right", "front", "back"}
  6. local foundAny = false
  7.  
  8. for _, side in ipairs(sides) do
  9. if peripheral.isPresent(side) then
  10. foundAny = true
  11. local name = peripheral.getType(side)
  12. term.setTextColor(colors.lime)
  13. print("[FOUND] " .. name .. " at " .. side)
  14. else
  15. term.setTextColor(colors.red)
  16. print("[NOT FOUND] No peripheral at " .. side)
  17. end
  18. end
  19.  
  20. if not foundAny then
  21. term.setTextColor(colors.yellow)
  22. print("\nNo peripherals found.")
  23. end
  24.  
  25. term.setTextColor(colors.white) -- Reset color
  26. end
  27.  
  28. scanPeripherals()
  29.  
  30.  
  31. -- QuartzDE - A Basic Desktop Environment for CraftOS (CC: Tweaked)
  32. -- Features:
  33. -- • Draggable & Resizable Windows with a full window frame (title bar, close and resize handles)
  34. -- • Programs Menu (with an "Exit Desktop" option)
  35. -- • Program windows run inside an inner content area so that the frame remains intact.
  36. -- • For games, if they don’t naturally render well in a window, they are centered
  37. -- and a "[Close Game]" button is provided in the content area.
  38. -- Credits: Made by Orion on 16th March 25
  39.  
  40. -- List of available programs
  41. local programs = {
  42. {name = "redirection", path = "redirection"},
  43. {name = "worm", path = "worm"},
  44. {name = "About QuartzDE", path = "about"},
  45. {name = "Exit Desktop", path = "exit"}
  46. }
  47.  
  48. -- Global variables for window management
  49. local windows = {}
  50. local windowID = 0
  51. local draggingWindow = nil
  52. local resizingWindow = nil
  53. local dragOffsetX, dragOffsetY = 0, 0
  54. local screenW, screenH = term.getSize()
  55. local exitRequested = false
  56. local minWidth, minHeight = 20, 5
  57.  
  58. math.randomseed(os.time())
  59.  
  60. --------------------------------------------------
  61. -- Window Manager Functions
  62. --------------------------------------------------
  63. -- createWindow creates a new window record.
  64. -- The parameter 'content' is a function(innerWin, win) that draws the inner content.
  65. local function createWindow(title, x, y, w, h, content)
  66. windowID = windowID + 1
  67. local win = {
  68. id = windowID,
  69. title = title or "Untitled",
  70. x = x or 5,
  71. y = y or 5,
  72. w = w or 30,
  73. h = h or 10,
  74. visible = true,
  75. content = content, -- function(innerWindow, win) for inner drawing
  76. programStarted = false, -- used for program windows so they run only once
  77. programFinished = false, -- becomes true when the program has finished running
  78. waitForKey = false, -- if true, the window is waiting for a key to close
  79. closeButton = nil -- for game windows: absolute coords for the [Close Game] button
  80. }
  81. table.insert(windows, win)
  82. return win
  83. end
  84.  
  85. -- drawDesktop clears the background.
  86. local function drawDesktop()
  87. term.setBackgroundColor(colors.blue)
  88. term.clear()
  89. end
  90.  
  91. -- drawWindow draws a complete window:
  92. -- 1. Creates the outer frame (using a dedicated window) and draws:
  93. -- - A title bar (line 1) with the window title and a frame close button ("X").
  94. -- - A resize handle ("+") at the bottom–right corner.
  95. -- 2. Then creates an inner content area (a sub–window) that occupies the region
  96. -- inside the frame (leaving a 1–cell border) and calls win.content(innerWin, win) if provided.
  97. local function drawWindow(win)
  98. local frame = window.create(term.current(), win.x, win.y, win.w, win.h)
  99. frame.setBackgroundColor(colors.gray)
  100. frame.clear()
  101.  
  102. -- Draw title bar on first line of the frame
  103. frame.setBackgroundColor(colors.lightGray)
  104. frame.setTextColor(colors.black)
  105. frame.setCursorPos(1, 1)
  106. frame.write(string.rep(" ", win.w))
  107. frame.setCursorPos(2, 1)
  108. frame.write(win.title)
  109.  
  110. -- Draw close button ("X") in top–right corner of the frame
  111. local closeX = win.w - 1
  112. frame.setCursorPos(closeX, 1)
  113. frame.setTextColor(colors.red)
  114. frame.write("X")
  115.  
  116. -- Draw resize handle ("+") at bottom–right corner of the frame
  117. frame.setCursorPos(win.w, win.h)
  118. frame.setTextColor(colors.white)
  119. frame.write("+")
  120.  
  121. -- Create inner content area.
  122. -- The inner window is inset by 1 cell on left and top and leaves a border.
  123. local inner = window.create(frame, 2, 2, win.w - 2, win.h - 2)
  124. if win.content then
  125. win.content(inner, win)
  126. end
  127. frame.redraw()
  128. inner.redraw()
  129. end
  130.  
  131. -- Helper functions for mouse hit detection on the outer frame:
  132. local function isInWindow(win, mx, my)
  133. return (mx >= win.x and mx < win.x + win.w) and (my >= win.y and my < win.y + win.h)
  134. end
  135.  
  136. local function isInTitleBar(win, mx, my)
  137. return isInWindow(win, mx, my) and (my == win.y)
  138. end
  139.  
  140. local function isInCloseButton(win, mx, my)
  141. return (my == win.y) and (mx >= win.x + win.w - 2 and mx < win.x + win.w)
  142. end
  143.  
  144. local function isInResizeHandle(win, mx, my)
  145. return (mx >= win.x + win.w - 2 and mx < win.x + win.w) and (my >= win.y + win.h - 1 and my < win.y + win.h)
  146. end
  147.  
  148. -- Bring a window to the front (end of the windows table).
  149. local function bringToFront(index)
  150. local win = table.remove(windows, index)
  151. table.insert(windows, win)
  152. end
  153.  
  154. --------------------------------------------------
  155. -- Taskbar & Programs Menu Functions
  156. --------------------------------------------------
  157. local function drawTaskbar()
  158. local w, h = term.getSize()
  159. term.setBackgroundColor(colors.gray)
  160. term.setTextColor(colors.white)
  161. term.setCursorPos(1, h)
  162. term.write(string.rep(" ", w)) -- Clear the taskbar line
  163. term.setCursorPos(1, h)
  164. term.write(" [Programs] ")
  165. end
  166.  
  167. -- showProgramMenu displays a simple menu above the taskbar.
  168. -- It returns the selected program (a table) or nil if canceled.
  169. local function showProgramMenu()
  170. local menuWidth = 20
  171. local menuHeight = #programs
  172. local w, h = term.getSize()
  173. local startX = 1
  174. local startY = h - menuHeight - 1
  175. local menuWin = window.create(term.current(), startX, startY, menuWidth, menuHeight)
  176.  
  177. menuWin.setBackgroundColor(colors.lightGray)
  178. menuWin.clear()
  179. for i, item in ipairs(programs) do
  180. menuWin.setCursorPos(2, i)
  181. menuWin.setTextColor(colors.black)
  182. menuWin.write(item.name)
  183. end
  184. menuWin.redraw()
  185.  
  186. local selection = nil
  187. local event, button, mx, my = os.pullEvent("mouse_click")
  188. if mx >= startX and mx < startX + menuWidth and my >= startY and my < startY + menuHeight then
  189. local index = my - startY + 1
  190. selection = programs[index]
  191. end
  192.  
  193. menuWin.clear()
  194. menuWin = nil
  195. return selection
  196. end
  197.  
  198. --------------------------------------------------
  199. -- Program Launcher: Creates a window for the program.
  200. --------------------------------------------------
  201. local function runProgram(prog)
  202. if prog.path == "exit" then
  203. exitRequested = true
  204. return
  205. end
  206.  
  207. local x, y, w, h
  208. if prog.path == "about" then
  209. w, h = 40, 12
  210. x = math.floor((screenW - w) / 2) + 1
  211. y = math.floor((screenH - h) / 2) + 1
  212. else
  213. w, h = 50, 15
  214. x = math.floor((screenW - w) / 2) + 1
  215. y = math.floor((screenH - h) / 2) + 1
  216. end
  217.  
  218. local contentFunction = nil
  219. if prog.path == "about" then
  220. -- The About window draws credits in the inner content area.
  221. contentFunction = function(inner, win)
  222. inner.setBackgroundColor(colors.black)
  223. inner.clear()
  224. inner.setCursorPos(1, 1)
  225. inner.setTextColor(colors.white)
  226. inner.write("QuartzDE Desktop Environment")
  227. inner.setCursorPos(1, 2)
  228. inner.write("Made by Orion")
  229. inner.setCursorPos(1, 3)
  230. inner.write("Made on 16th March 25")
  231. inner.setCursorPos(1, 5)
  232. inner.write("Press any key to close")
  233. win.waitForKey = true
  234. inner.redraw()
  235. end
  236. else
  237. -- For games (or other programs), run them inside the inner window.
  238. contentFunction = function(inner, win)
  239. if not win.programStarted then
  240. win.programStarted = true
  241. inner.setBackgroundColor(colors.black)
  242. inner.clear()
  243. local oldTerm = term.redirect(inner)
  244. shell.run(prog.path)
  245. term.redirect(oldTerm)
  246. win.programFinished = true
  247. end
  248. -- Draw a [Close Game] button in the inner area (bottom center).
  249. local cw = win.w - 2 -- inner width
  250. local ch = win.h - 2 -- inner height
  251. local buttonText = "[Close Game]"
  252. local btnWidth = string.len(buttonText)
  253. local btnX = math.floor((cw - btnWidth) / 2) + 1
  254. local btnY = ch -- bottom line of inner area
  255. inner.setCursorPos(btnX, btnY)
  256. inner.setTextColor(colors.white)
  257. inner.write(buttonText)
  258. inner.redraw()
  259. -- Calculate absolute position of the button for mouse detection.
  260. win.closeButton = {
  261. x = win.x + btnX, -- inner window is at win.x+1, but btnX is relative to inner's start at 1
  262. y = win.y + btnY, -- similarly for y
  263. width = btnWidth,
  264. height = 1
  265. }
  266. end
  267. end
  268.  
  269. createWindow(prog.name, x, y, w, h, contentFunction)
  270. end
  271.  
  272. --------------------------------------------------
  273. -- Main Desktop Loop Setup (with two demo windows)
  274. --------------------------------------------------
  275. -- Demo windows (non–program windows)
  276. createWindow("Window 1", 10, 5, 30, 10, function(inner, win)
  277. inner.setBackgroundColor(colors.black)
  278. inner.clear()
  279. inner.setCursorPos(1, 1)
  280. inner.setTextColor(colors.white)
  281. inner.write("This is a demo window.")
  282. inner.redraw()
  283. end)
  284. createWindow("Window 2", 20, 8, 30, 10, function(inner, win)
  285. inner.setBackgroundColor(colors.black)
  286. inner.clear()
  287. inner.setCursorPos(1, 1)
  288. inner.setTextColor(colors.white)
  289. inner.write("Another demo window.")
  290. inner.redraw()
  291. end)
  292.  
  293. --------------------------------------------------
  294. -- Main Desktop Loop
  295. --------------------------------------------------
  296. while not exitRequested do
  297. drawDesktop()
  298. for _, win in ipairs(windows) do
  299. if win.visible then
  300. drawWindow(win)
  301. end
  302. end
  303. drawTaskbar()
  304.  
  305. local event, a, b, c, d = os.pullEvent()
  306.  
  307. if event == "mouse_click" then
  308. local button, mx, my = a, b, c
  309. local screenW, screenH = term.getSize()
  310. local handled = false
  311.  
  312. -- First, check if the click hits any inner [Close Game] button (if defined).
  313. for i = #windows, 1, -1 do
  314. local win = windows[i]
  315. if win.visible and win.closeButton then
  316. local cb = win.closeButton
  317. if mx >= cb.x and mx < cb.x + cb.width and my >= cb.y and my < cb.y + cb.height then
  318. win.visible = false
  319. handled = true
  320. break
  321. end
  322. end
  323. end
  324. if handled then goto continue_mouse_click end
  325.  
  326. -- Check if the click is on the taskbar (bottom row)
  327. if my == screenH then
  328. if mx >= 1 and mx <= 11 then
  329. local selected = showProgramMenu()
  330. if selected then
  331. runProgram(selected)
  332. end
  333. end
  334. else
  335. -- Check windows in reverse order (topmost first)
  336. for i = #windows, 1, -1 do
  337. local win = windows[i]
  338. if win.visible and isInWindow(win, mx, my) then
  339. bringToFront(i)
  340. if isInResizeHandle(win, mx, my) then
  341. resizingWindow = win
  342. break
  343. elseif isInCloseButton(win, mx, my) then
  344. win.visible = false
  345. break
  346. elseif isInTitleBar(win, mx, my) then
  347. draggingWindow = win
  348. dragOffsetX = mx - win.x
  349. dragOffsetY = my - win.y
  350. break
  351. end
  352. break
  353. end
  354. end
  355. end
  356. ::continue_mouse_click::
  357.  
  358. elseif event == "mouse_drag" then
  359. local button, mx, my = a, b, c
  360. if draggingWindow then
  361. draggingWindow.x = math.max(1, math.min(mx - dragOffsetX, screenW - draggingWindow.w + 1))
  362. draggingWindow.y = math.max(1, math.min(my - dragOffsetY, screenH - draggingWindow.h))
  363. elseif resizingWindow then
  364. local newW = math.max(minWidth, mx - resizingWindow.x + 1)
  365. local newH = math.max(minHeight, my - resizingWindow.y + 1)
  366. resizingWindow.w = newW
  367. resizingWindow.h = newH
  368. end
  369.  
  370. elseif event == "mouse_up" then
  371. draggingWindow = nil
  372. resizingWindow = nil
  373.  
  374. elseif event == "key" then
  375. -- If any window is waiting for a key to close (e.g. About), close it.
  376. for i = #windows, 1, -1 do
  377. local win = windows[i]
  378. if win.visible and win.waitForKey then
  379. win.visible = false
  380. win.waitForKey = false
  381. break
  382. end
  383. end
  384. end
  385. end
  386.  
  387. -- Exit: Reset the terminal
  388. term.setBackgroundColor(colors.black)
  389. term.clear()
  390. term.setCursorPos(1,1)
  391.  
Advertisement
Add Comment
Please, Sign In to add comment