autoupdater.lua

642 lines · 20.9 KB

Open raw

CCOMMANDER AUTOUPDATER

Copy & run

wget https://perlytiara.github.io/turtles.tips/raw/programs/perlytiara/cCommander/autoupdater.lua
1-- CCOMMANDER AUTOUPDATER
2-- Auto-updates programs based on turtle type detection
3-- Supports mining turtle, chunky turtle, and controller configurations
4
5local w, h = term.getSize()
6local currentPage = 1
7local totalPages = 1
8local lines = {}
9local turtleType = "unknown"
10local selectedOption = 1
11local maxOptions = 5
12local startOption = 1
13local optionsPerPage = 5
14local installPath = "programs/perlytiara/cCommander/"
15local useExtension = true
16local settingsFile = ".ccommander_settings"
17
18-- Colors for better UI
19local colors = {
20 white = colors.white,
21 gray = colors.gray,
22 black = colors.black,
23 blue = colors.blue,
24 green = colors.green,
25 red = colors.red,
26 yellow = colors.yellow,
27 orange = colors.orange
28}
29
30-- Repository configuration
31local REPO_BASE = "https://raw.githubusercontent.com/perlytiara/CC-Tweaked-TurtsAndComputers/refs/heads/main/programs/perlytiara/cCommander/"
32local PROGRAMS_FOLDER = "programs/perlytiara/cCommander/"
33
34-- Program definitions by turtle type
35local PROGRAM_CONFIGS = {
36 mining_turtle = {
37 name = "Mining Turtle",
38 programs = {
39 {name = "AdvancedMiningTurtle", file = "AdvancedMiningTurtle.lua", description = "Advanced wireless mining turtle"},
40 {name = "mining_controller", file = "mining_controller.lua", description = "Mining controller interface"}
41 }
42 },
43 chunky_turtle = {
44 name = "Chunky Turtle",
45 programs = {
46 {name = "AdvancedChunkyTurtle", file = "AdvancedChunkyTurtle.lua", description = "Advanced chunky turtle"},
47 {name = "chunky_controller", file = "chunky_controller.lua", description = "Chunky controller interface"}
48 }
49 },
50 controller = {
51 name = "Controller",
52 programs = {
53 {name = "AdvancedMiningController", file = "AdvancedMiningController.lua", description = "Advanced mining controller"},
54 {name = "controller_interface", file = "controller_interface.lua", description = "Controller management interface"}
55 }
56 },
57 deployment = {
58 name = "Deployment System",
59 programs = {
60 {name = "turtle_deployer", file = "turtle_deployer.lua", description = "Turtle deployment system"},
61 {name = "chest_manager", file = "chest_manager.lua", description = "Chest management system"},
62 {name = "test_bootup", file = "test_bootup.lua", description = "Test boot-up system"},
63 {name = "linear_deployer", file = "linear_deployer.lua", description = "Linear step-by-step deployer"},
64 {name = "simple_deployer", file = "simple_deployer.lua", description = "Simple deployment test"},
65 {name = "chest_test", file = "chest_test.lua", description = "Chest interaction test"},
66 {name = "server_spawner", file = "server_spawner.lua", description = "Server command spawner"},
67 {name = "wireless_spawner", file = "wireless_spawner.lua", description = "Wireless command spawner"}
68 }
69 },
70 all = {
71 name = "All Programs",
72 programs = {
73 {name = "AdvancedMiningTurtle", file = "AdvancedMiningTurtle.lua", description = "Advanced wireless mining turtle"},
74 {name = "AdvancedChunkyTurtle", file = "AdvancedChunkyTurtle.lua", description = "Advanced chunky turtle"},
75 {name = "AdvancedMiningController", file = "AdvancedMiningController.lua", description = "Advanced mining controller"},
76 {name = "turtle_deployer", file = "turtle_deployer.lua", description = "Turtle deployment system"},
77 {name = "chest_manager", file = "chest_manager.lua", description = "Chest management system"},
78 {name = "test_bootup", file = "test_bootup.lua", description = "Test boot-up system"},
79 {name = "linear_deployer", file = "linear_deployer.lua", description = "Linear step-by-step deployer"},
80 {name = "simple_deployer", file = "simple_deployer.lua", description = "Simple deployment test"},
81 {name = "chest_test", file = "chest_test.lua", description = "Chest interaction test"},
82 {name = "server_spawner", file = "server_spawner.lua", description = "Server command spawner"},
83 {name = "wireless_spawner", file = "wireless_spawner.lua", description = "Wireless command spawner"},
84 {name = "autoupdater", file = "autoupdater.lua", description = "This updater"}
85 }
86 }
87}
88
89-- Utility functions
90function loadSettings()
91 if fs.exists(settingsFile) then
92 local file = fs.open(settingsFile, "r")
93 if file then
94 local content = file.readAll()
95 file.close()
96
97 -- Parse settings from file
98 for line in content:gmatch("[^\r\n]+") do
99 if line:match("^installPath=") then
100 installPath = line:match("installPath=(.+)")
101 elseif line:match("^useExtension=") then
102 useExtension = line:match("useExtension=(.+)") == "true"
103 end
104 end
105 end
106 end
107end
108
109function saveSettings()
110 local file = fs.open(settingsFile, "w")
111 if file then
112 file.write("installPath=" .. installPath .. "\n")
113 file.write("useExtension=" .. tostring(useExtension) .. "\n")
114 file.close()
115 end
116end
117
118function detectTurtleType()
119 -- Check if we have a mining turtle (has mining tools)
120 local hasPickaxe = false
121 for slot = 1, 16 do
122 local item = turtle.getItemDetail(slot)
123 if item and (item.name:match("pickaxe") or item.name:match("drill")) then
124 hasPickaxe = true
125 break
126 end
127 end
128
129 if hasPickaxe then
130 return "mining_turtle"
131 end
132
133 -- Check if we have controller programs
134 if fs.exists("AdvancedMiningController.lua") or fs.exists(PROGRAMS_FOLDER .. "AdvancedMiningController.lua") then
135 return "controller"
136 end
137
138 -- Check if we have chunky turtle programs
139 if fs.exists("AdvancedChunkyTurtle.lua") or fs.exists(PROGRAMS_FOLDER .. "AdvancedChunkyTurtle.lua") then
140 return "chunky_turtle"
141 end
142
143 -- Check if we have deployment programs
144 if fs.exists("turtle_deployer.lua") or fs.exists(PROGRAMS_FOLDER .. "turtle_deployer.lua") then
145 return "deployment"
146 end
147
148 -- Default to all if we can't determine
149 return "all"
150end
151
152function clearScreen()
153 term.clear()
154 term.setCursorPos(1, 1)
155end
156
157function centerText(text, y)
158 local x = math.floor((w - string.len(text)) / 2) + 1
159 if x < 1 then x = 1 end
160 term.setCursorPos(x, y)
161 write(text)
162end
163
164function drawHeader()
165 term.setTextColor(colors.blue)
166 centerText("===================", 1)
167 centerText(" CCOMMANDER UPDATER ", 2)
168 centerText("===================", 3)
169 term.setTextColor(colors.white)
170end
171
172function drawFooter()
173 local y = h
174 term.setTextColor(colors.gray)
175 term.setCursorPos(1, y)
176 write("Arrows:Navigate | Enter:Select | Q:Quit")
177end
178
179function highlightOption(optionNum, text, y)
180 if optionNum == selectedOption then
181 term.setTextColor(colors.black)
182 term.setBackgroundColor(colors.white)
183 term.setCursorPos(2, y)
184 write("> " .. text)
185 term.setTextColor(colors.white)
186 term.setBackgroundColor(colors.black)
187 else
188 term.setTextColor(colors.blue)
189 term.setCursorPos(2, y)
190 write(" " .. text)
191 end
192end
193
194function splitText(text, width)
195 local words = {}
196 for word in text:gmatch("%S+") do
197 table.insert(words, word)
198 end
199
200 local lines = {}
201 local currentLine = ""
202
203 for _, word in ipairs(words) do
204 if string.len(currentLine .. " " .. word) <= width then
205 if currentLine == "" then
206 currentLine = word
207 else
208 currentLine = currentLine .. " " .. word
209 end
210 else
211 if currentLine ~= "" then
212 table.insert(lines, currentLine)
213 currentLine = word
214 else
215 table.insert(lines, word)
216 end
217 end
218 end
219
220 if currentLine ~= "" then
221 table.insert(lines, currentLine)
222 end
223
224 return lines
225end
226
227function displayText(text, startY)
228 lines = splitText(text, w - 2)
229 totalPages = math.max(1, math.ceil(#lines / (h - startY - 2)))
230
231 local startLine = (currentPage - 1) * (h - startY - 2) + 1
232 local endLine = math.min(startLine + (h - startY - 2) - 1, #lines)
233
234 for i = startLine, endLine do
235 if lines[i] then
236 term.setCursorPos(2, startY + (i - startLine))
237 write(lines[i])
238 end
239 end
240end
241
242function downloadProgram(programInfo, description)
243 local url = REPO_BASE .. programInfo.file
244 local finalPath = installPath .. programInfo.name
245 if useExtension then
246 finalPath = finalPath .. ".lua"
247 end
248
249 -- Ensure install folder exists
250 local pathParts = {}
251 for part in installPath:gmatch("[^/]+") do
252 table.insert(pathParts, part)
253 end
254
255 local currentPath = ""
256 for _, part in ipairs(pathParts) do
257 currentPath = currentPath .. part .. "/"
258 if not fs.exists(currentPath) then
259 fs.makeDir(currentPath)
260 end
261 end
262
263 -- Remove old file if it exists
264 if fs.exists(finalPath) then
265 fs.delete(finalPath)
266 end
267
268 clearScreen()
269 drawHeader()
270
271 -- Compact layout for small terminals
272 local startY = 5
273 if h < 15 then
274 startY = 4
275 end
276
277 term.setTextColor(colors.yellow)
278 centerText("Downloading: " .. programInfo.name, startY)
279 term.setTextColor(colors.white)
280
281 term.setCursorPos(2, startY + 1)
282 write("From: " .. url)
283 term.setCursorPos(2, startY + 2)
284 write("To: " .. finalPath)
285 term.setCursorPos(2, startY + 3)
286 write("Desc: " .. description)
287
288 term.setTextColor(colors.blue)
289 term.setCursorPos(2, startY + 5)
290 write("Status: Downloading...")
291
292 -- Download the file
293 local success, errorMsg = pcall(function()
294 shell.run("wget", url, finalPath)
295 end)
296
297 if success then
298 term.setTextColor(colors.green)
299 term.setCursorPos(2, startY + 5)
300 write("Status: Success!")
301 else
302 term.setTextColor(colors.red)
303 term.setCursorPos(2, startY + 5)
304 write("Status: Failed!")
305 term.setCursorPos(2, startY + 6)
306 write("Error: " .. tostring(errorMsg))
307 end
308
309 term.setTextColor(colors.white)
310 term.setCursorPos(2, h - 1)
311 write("Press any key...")
312 os.pullEvent("key")
313end
314
315function showMainMenu()
316 clearScreen()
317 drawHeader()
318
319 -- Compact layout for small terminals
320 local startY = 5
321 if h < 15 then
322 startY = 4
323 end
324
325 term.setTextColor(colors.green)
326 term.setCursorPos(2, startY)
327 write("Type: " .. turtleType)
328
329 term.setTextColor(colors.white)
330 term.setCursorPos(2, startY + 1)
331 write("Options:")
332
333 local y = startY + 2
334 local config = PROGRAM_CONFIGS[turtleType]
335
336 -- Option 1: Update detected turtle type programs
337 if config then
338 highlightOption(1, "Update " .. config.name, y)
339 else
340 highlightOption(1, "Update Detected", y)
341 end
342 y = y + 1
343
344 -- Option 2: Update all programs
345 highlightOption(2, "Update All", y)
346 y = y + 1
347
348 -- Option 3: Manual selection
349 highlightOption(3, "Manual Select", y)
350 y = y + 1
351
352 -- Option 4: Settings
353 highlightOption(4, "Settings", y)
354 y = y + 1
355
356 -- Option 5: Exit
357 highlightOption(5, "Exit", y)
358
359 drawFooter()
360end
361
362function updatePrograms(config)
363 clearScreen()
364 drawHeader()
365
366 term.setTextColor(colors.yellow)
367 centerText("Updating " .. config.name .. " Programs", 5)
368 term.setTextColor(colors.white)
369
370 for i, program in ipairs(config.programs) do
371 term.setCursorPos(2, 7 + (i - 1) * 2)
372 write(string.format("[%d/%d] %s", i, #config.programs, program.file))
373
374 downloadProgram(program, program.description)
375 end
376
377 clearScreen()
378 drawHeader()
379 term.setTextColor(colors.green)
380 centerText("All programs updated successfully!", 5)
381 term.setTextColor(colors.white)
382 term.setCursorPos(2, 7)
383 write("Press any key to return to main menu...")
384 os.pullEvent("key")
385end
386
387function showManualSelection()
388 local programs = PROGRAM_CONFIGS.all.programs
389 local manualSelectedOption = 1
390 local currentPage = 1
391 local itemsPerPage = math.max(1, h - 10) -- Leave room for header, footer, and page info
392 local totalPages = math.ceil(#programs / itemsPerPage)
393
394 while true do
395 clearScreen()
396 drawHeader()
397
398 term.setTextColor(colors.yellow)
399 centerText("Manual Select", 5)
400 term.setTextColor(colors.white)
401
402 -- Calculate which items to show on current page
403 local startItem = (currentPage - 1) * itemsPerPage + 1
404 local endItem = math.min(startItem + itemsPerPage - 1, #programs)
405 local pageSelectedOption = manualSelectedOption - (currentPage - 1) * itemsPerPage
406
407 -- Show page info
408 term.setTextColor(colors.gray)
409 term.setCursorPos(2, 6)
410 write("Page " .. currentPage .. "/" .. totalPages .. " (" .. startItem .. "-" .. endItem .. " of " .. #programs .. ")")
411
412 local y = 7
413
414 -- Show programs for current page
415 for i = startItem, endItem do
416 local program = programs[i]
417 local displayIndex = i - startItem + 1
418
419 if i == manualSelectedOption then
420 -- Show selected option with highlighting
421 term.setTextColor(colors.black)
422 term.setBackgroundColor(colors.white)
423 term.setCursorPos(2, y)
424 write("> " .. program.name)
425 term.setTextColor(colors.white)
426 term.setBackgroundColor(colors.black)
427 else
428 -- Show unselected option
429 term.setTextColor(colors.blue)
430 term.setCursorPos(2, y)
431 write(" " .. program.name)
432 end
433 y = y + 1
434 end
435
436 -- Footer with navigation info
437 term.setTextColor(colors.gray)
438 term.setCursorPos(1, h)
439 if totalPages > 1 then
440 write("Arrows:Navigate | Page Up/Down:Page | Enter:Select | Q:Back")
441 else
442 write("Arrows:Navigate | Enter:Select | Q:Back")
443 end
444
445 local event, key = os.pullEvent("key")
446
447 if key == keys.q or key == keys.escape then
448 return
449 elseif key == keys.up then
450 if manualSelectedOption > 1 then
451 manualSelectedOption = manualSelectedOption - 1
452 -- Check if we need to change pages
453 if manualSelectedOption <= (currentPage - 1) * itemsPerPage then
454 currentPage = currentPage - 1
455 end
456 end
457 elseif key == keys.down then
458 if manualSelectedOption < #programs then
459 manualSelectedOption = manualSelectedOption + 1
460 -- Check if we need to change pages
461 if manualSelectedOption > currentPage * itemsPerPage then
462 currentPage = currentPage + 1
463 end
464 end
465 elseif key == keys.pageUp then
466 if currentPage > 1 then
467 currentPage = currentPage - 1
468 manualSelectedOption = math.min(manualSelectedOption, currentPage * itemsPerPage)
469 end
470 elseif key == keys.pageDown then
471 if currentPage < totalPages then
472 currentPage = currentPage + 1
473 manualSelectedOption = math.max(manualSelectedOption, (currentPage - 1) * itemsPerPage + 1)
474 end
475 elseif key == keys.enter then
476 downloadProgram(programs[manualSelectedOption], programs[manualSelectedOption].description)
477 return
478 end
479 end
480end
481
482function showSettings()
483 local settingsSelected = 1
484 local maxSettings = 3
485
486 while true do
487 clearScreen()
488 drawHeader()
489
490 term.setTextColor(colors.yellow)
491 centerText("Settings", 5)
492 term.setTextColor(colors.white)
493
494 term.setCursorPos(2, 7)
495 write("Install Path: " .. installPath)
496 term.setCursorPos(2, 8)
497 write("Use .lua extension: " .. (useExtension and "Yes" or "No"))
498 term.setCursorPos(2, 9)
499 write("Current: " .. turtleType)
500
501 local y = 11
502 if settingsSelected == 1 then
503 highlightOption(1, "Change Install Path", y)
504 else
505 term.setTextColor(colors.blue)
506 term.setCursorPos(2, y)
507 write("Change Install Path")
508 end
509 y = y + 1
510
511 if settingsSelected == 2 then
512 highlightOption(2, "Toggle .lua Extension", y)
513 else
514 term.setTextColor(colors.blue)
515 term.setCursorPos(2, y)
516 write("Toggle .lua Extension")
517 end
518 y = y + 1
519
520 if settingsSelected == 3 then
521 highlightOption(3, "Back to Menu", y)
522 else
523 term.setTextColor(colors.blue)
524 term.setCursorPos(2, y)
525 write("Back to Menu")
526 end
527
528 term.setTextColor(colors.gray)
529 term.setCursorPos(1, h)
530 write("Arrows:Navigate | Enter:Select | Q:Back")
531
532 local event, key = os.pullEvent("key")
533
534 if key == keys.q or key == keys.escape then
535 return
536 elseif key == keys.up then
537 if settingsSelected > 1 then
538 settingsSelected = settingsSelected - 1
539 end
540 elseif key == keys.down then
541 if settingsSelected < maxSettings then
542 settingsSelected = settingsSelected + 1
543 end
544 elseif key == keys.enter then
545 if settingsSelected == 1 then
546 clearScreen()
547 drawHeader()
548 term.setTextColor(colors.white)
549 term.setCursorPos(2, 5)
550 write("Enter install path:")
551 term.setCursorPos(2, 6)
552 write("(e.g., programs/myfolder/ or just /)")
553 term.setCursorPos(2, 8)
554 write("Current: " .. installPath)
555 term.setCursorPos(2, 10)
556 write("New path: ")
557 local newPath = read()
558 if newPath and newPath ~= "" then
559 installPath = newPath
560 if not installPath:match("/$") then
561 installPath = installPath .. "/"
562 end
563 saveSettings()
564 end
565 elseif settingsSelected == 2 then
566 useExtension = not useExtension
567 saveSettings()
568 elseif settingsSelected == 3 then
569 return
570 end
571 end
572 end
573end
574
575function main()
576 -- Load saved settings
577 loadSettings()
578
579 -- Detect turtle type
580 turtleType = detectTurtleType()
581
582 while true do
583 showMainMenu()
584
585 local event, key = os.pullEvent("key")
586
587 if key == keys.q or key == keys.escape then
588 clearScreen()
589 term.setCursorPos(1, 1)
590 return
591 elseif key == keys.up then
592 if selectedOption > 1 then
593 selectedOption = selectedOption - 1
594 -- Adjust scrolling window if needed
595 local availableHeight = h - 10
596 local optionHeight = 3
597 local maxVisibleOptions = math.floor(availableHeight / optionHeight)
598
599 if selectedOption < startOption then
600 startOption = selectedOption
601 end
602
603 showMainMenu()
604 end
605 elseif key == keys.down then
606 if selectedOption < maxOptions then
607 selectedOption = selectedOption + 1
608 -- Adjust scrolling window if needed
609 local availableHeight = h - 10
610 local optionHeight = 3
611 local maxVisibleOptions = math.floor(availableHeight / optionHeight)
612
613 if selectedOption > startOption + maxVisibleOptions - 1 then
614 startOption = selectedOption - maxVisibleOptions + 1
615 end
616
617 showMainMenu()
618 end
619 elseif key == keys.enter then
620 if selectedOption == 1 then
621 local config = PROGRAM_CONFIGS[turtleType]
622 if config then
623 updatePrograms(config)
624 end
625 elseif selectedOption == 2 then
626 updatePrograms(PROGRAM_CONFIGS.all)
627 elseif selectedOption == 3 then
628 showManualSelection()
629 elseif selectedOption == 4 then
630 showSettings()
631 elseif selectedOption == 5 then
632 clearScreen()
633 term.setCursorPos(1, 1)
634 return
635 end
636 end
637 end
638end
639
640-- Start the updater
641main()
642