· 4 years ago · Jun 09, 2021, 05:26 PM
1--/ Dynamic Shop / Reactified /--
2local chest = peripheral.wrap("top")
3
4--/ Initialization /--
5os.pullEvent = os.pullEventRaw
6local currency = "CSH"
7local errors = {}
8local m = peripheral.find("monitor")
9
10if (type(chest) ~= "table") or (chest and not chest.size) then
11 chest = nil
12end
13
14--/ Data Persistence /--
15local data = {
16 size = 0.5,
17 price_change_time = 120,
18 price_change_magnitude = 0,
19 price_increase_magnitude = 0,
20 drop = "down",
21}
22local init = false
23local function saveData()
24 f = fs.open("/.shopdata","w")
25 f.writeLine(textutils.serialise(data))
26 f.close()
27end
28if fs.exists('/.shopdata') then
29 f = fs.open("/.shopdata","r")
30 data = textutils.unserialise(f.readAll())
31 f.close()
32else
33 init = true
34end
35
36--/ ID System /--
37local function genID(item)
38 return item.name.."/"..tostring(item.damage or item.nbt)
39end
40
41--/ Item Dispensing /--
42local dropFunction = turtle.dropDown
43if data.drop == "down" then
44 dropFunction = turtle.dropDown
45elseif data.drop == "forward" then
46 dropFunction = turtle.drop
47elseif data.drop == "up" then
48 dropFunction = turtle.dropUp
49end
50
51local function dispenseItem(itemID, amount)
52 if amount > 0 then
53 if chest then
54 -- chest dispensing routine
55 for slot,slotData in pairs(chest.list()) do
56 local data = chest.getItemDetail(slot)
57 if data and genID(data) == itemID then
58 if amount > slotData.count then
59 chest.pushItems(peripheral.getName(chest),slot,slotData.count,1)
60 turtle.suckUp(slotData.count)
61 dropFunction()
62 amount = amount - slotData.count
63 else
64 chest.pushItems(peripheral.getName(chest),slot,amount,1)
65 turtle.suckUp(amount)
66 dropFunction()
67 amount = 0
68 end
69 end
70 end
71 else
72 -- turtle inventory dispensing routine
73 for slot=1,16 do
74 local data = turtle.getItemDetail(slot)
75 if data and genID(data) == itemID then
76 turtle.select(slot)
77 if amount > turtle.getItemCount() then
78 local ct = turtle.getItemCount()
79 dropFunction()
80 amount = amount - ct
81 else
82 dropFunction(amount)
83 amount = 0
84 end
85 end
86 end
87 end
88 end
89end
90
91--/ API Imports /--
92os.loadAPI("/apis/sha256.lua")
93os.loadAPI("/apis/ccash.lua")
94local api = _G["ccash"].simple
95
96--/ Fixed Tostring /--
97local function fixedTostring(number) -- simple tostring function that rounds off floating point errors
98 local str = tostring(number)
99 local hasPeriod = false
100 for i=1,#str do
101 local char = string.sub(str,i,i)
102 if char == "." then
103 hasPeriod = true
104 end
105 end
106 if hasPeriod then
107 for i=1,#str do
108 if string.sub(str,#str,#str) == "0" then
109 str = string.sub(str,1,#str-1)
110 end
111 end
112 end
113 return str
114end
115
116--/ Inventory Management /--
117local price_change_time = data.price_change_time -- How often the shop lowers prices
118local price_change_magnitude = data.price_change_magnitude -- How much the shop lowers prices
119local price_increase_magnitude = data.price_increase_magnitude -- How much prices increase per item sold
120local stock = {}
121local uncategorized = {}
122local chestFull = false
123local function invMgmt()
124 while init do
125 sleep(5)
126 end
127 while true do
128 nstock = {}
129 uncategorized = {}
130 if chest then
131 if chest.list()[1] then
132 for i=2,chest.size() do
133 local detail = chest.getItemDetail(i)
134 if not detail then
135 local firstSlotDetail = chest.getItemDetail(1)
136 chest.pushItems(peripheral.getName(chest),1,firstSlotDetail.count,i)
137 break
138 end
139 if i == chest.size() then
140 local oldX,oldY = term.getCursorPos()
141 local turtleW,turtleH = term.getSize()
142 term.setCursorPos(2,turtleH-1)
143 printError("Your chest is too full to operate.")
144 term.setCursorPos(oldX,oldY)
145 chestFull = true
146 end
147 end
148 else
149 chestFull = false
150 end
151 for i,v in pairs(chest.list()) do
152 local item = chest.getItemDetail(i)
153 if item then
154 local id = genID(item)
155 if data.products[id] then
156 nstock[id] = (nstock[id] or 0) + item.count
157 else
158 uncategorized[id] = true
159 end
160 end
161 end
162 else
163 for i=1,16 do
164 local item = turtle.getItemDetail(i)
165 if item then
166 local id = genID(item)
167 if data.products[id] then
168 nstock[id] = (nstock[id] or 0) + item.count
169 else
170 uncategorized[id] = true
171 end
172 end
173 end
174 end
175 stock = {}
176 for i,v in pairs(nstock) do
177 stock[#stock+1] = {i,v}
178 end
179 -- Dynamic Pricing
180 for i,v in pairs(data.products) do
181 if v.price_timer > price_change_time then
182 local delta = v.price - v.min_price
183 data.products[i].price = v.price - (delta * price_change_magnitude)
184 data.products[i].price_timer = 0
185 saveData()
186 end
187 data.products[i].price_timer = v.price_timer + 1
188 end
189 sleep(1)
190 end
191end
192
193--/ Remake Account /--
194if not init then
195 local bal = api.balance(data.username)
196 if bal == -1 then
197 api.register(data.username,data.password)
198 end
199end
200
201--/ Shop Routine /--
202local function shopRoutine()
203 -- Check Peripherals
204 if not m then
205 errors[#errors+1] = "No monitor detected."
206 elseif m and not m.isColor() then
207 errors[#errors+1] = "Advanced monitor required."
208 end
209 if #errors > 0 then
210 -- Abort Startup
211 os.pullEvent("INFINITE-YIELD")
212 end
213 -- UI Functions
214 m.setTextScale(data.size)
215 local w,h = m.getSize()
216 local function center(str,ln)
217 m.setCursorPos(1+(w/2)-(#str/2),ln)
218 m.write(str)
219 end
220 -- First Time Setup
221 while init do
222 m.setTextScale(0.5)
223 m.setBackgroundColor(colors.white)
224 m.clear()
225 m.setTextColor(colors.black)
226 center("Welcome!",h/2-2)
227 m.setTextColor(colors.gray)
228 center("Perform first time setup",h/2)
229 center("on the turtle's interface.",h/2+1)
230 m.setCursorPos(2,2)
231 m.setTextColor(colors.lightGray)
232 m.write(string.rep(".",w-2))
233 m.setCursorPos(2,h-1)
234 m.write(string.rep(".",w-2))
235 m.setTextColor(colors.lime)
236 for i=1,4 do
237 m.setCursorPos(math.random(2,w-2),2)
238 m.write(",")
239 m.setCursorPos(math.random(2,w-2),h-1)
240 m.write(",")
241 end
242 sleep(0.5)
243 end
244 -- Check for vault
245 local _,vaultExists = ccash.contains(data.vault)
246 if not vaultExists then
247 m.setBackgroundColor(colors.gray)
248 m.clear()
249 m.setBackgroundColor(data.color)
250 m.setCursorPos(1,1)
251 m.clearLine()
252 m.setCursorPos(1,2)
253 m.clearLine()
254 m.setCursorPos(1,3)
255 m.clearLine()
256 m.setCursorPos(2,2)
257 if data.color == colors.white then
258 m.setTextColor(colors.black)
259 else
260 m.setTextColor(colors.white)
261 end
262 center(data.name,2)
263 m.setBackgroundColor(colors.gray)
264 m.setTextColor(colors.white)
265 center("Shop out of service",h/2)
266 center("Vault account missing",h/2+1)
267 os.pullEvent("infinite-yield")
268 end
269 -- Routine
270 while true do
271 -- Draw Background
272 m.setBackgroundColor(colors.gray)
273 m.clear()
274 m.setBackgroundColor(data.color)
275 m.setCursorPos(1,1)
276 m.clearLine()
277 m.setCursorPos(1,2)
278 m.clearLine()
279 m.setCursorPos(1,3)
280 m.clearLine()
281 m.setCursorPos(2,2)
282 if data.color == colors.white then
283 m.setTextColor(colors.black)
284 else
285 m.setTextColor(colors.white)
286 end
287 center(data.name,2)
288 -- Products
289 m.setBackgroundColor(colors.gray)
290 m.setTextColor(colors.lightGray)
291 center("Right-click to purchase",h-2)
292 for i,v in pairs(stock) do
293 local product = data.products[v[1]]
294 if product then
295 m.setBackgroundColor(colors.gray)
296 m.setTextColor(colors.lightGray)
297 m.setCursorPos(1,4+(i*3))
298 m.write(string.rep(string.char(140),w))
299 m.setCursorPos(2,2+(i*3))
300 m.setTextColor(colors.lightGray)
301 m.write("> ")
302 m.setTextColor(data.color)
303 m.write(product.name)
304 m.setTextColor(colors.white)
305 local str = fixedTostring(math.floor(product.price*100)/100).." "..currency
306 m.setCursorPos(w-#str,2+(i*3))
307 m.write(str)
308 m.setCursorPos(2,3+(i*3))
309 m.setTextColor(colors.lightGray)
310 m.write(tostring(v[2]).."x in stock")
311 local str = "each"
312 m.setCursorPos(w-#str,3+(i*3))
313 m.write(str)
314 end
315 end
316 -- Event Handling
317 local tmr = os.startTimer(10)
318 while true do
319 local e,c,x,y = os.pullEvent()
320 if e == "timer" and c == tmr then
321 break
322 elseif e == "monitor_touch" and not chestFull then
323 local sel = stock[math.floor((y-2)/3)]
324 if sel then
325 local product = data.products[sel[1]]
326 local price = math.floor(product.price*100)/100
327 m.setBackgroundColor(colors.gray)
328 m.clear()
329 m.setBackgroundColor(data.color)
330 m.setCursorPos(1,1)
331 m.clearLine()
332 m.setCursorPos(1,2)
333 m.clearLine()
334 m.setCursorPos(1,3)
335 m.clearLine()
336 m.setCursorPos(2,2)
337 if data.color == colors.white then
338 m.setTextColor(colors.black)
339 else
340 m.setTextColor(colors.white)
341 end
342 center(data.name,2)
343 m.setBackgroundColor(colors.gray)
344 m.setTextColor(colors.lightGray)
345 center("Purchasing",5)
346 center("> Cancel <",h-1)
347 center("Send "..currency.." to",math.floor(h/2)+2)
348 center(fixedTostring(price).." "..currency.." / each",8)
349 m.setTextColor(data.color)
350 center(" "..data.username.." ",math.floor(h/2)+3)
351 center(product.name,7)
352 center(tostring(sel[2]).." available",h-3)
353 local function vendingFunction()
354 local state = 0
355 while true do
356 state = state + 1
357 if state == 1 or state == 6 then
358 center("------------------",math.floor(h/2)+1)
359 center("------------------",math.floor(h/2)+4)
360 if state == 6 then
361 state = 0
362 end
363 elseif state == 2 or state == 5 then
364 center(" ---------------- ",math.floor(h/2)+1)
365 center(" ---------------- ",math.floor(h/2)+4)
366 elseif state == 3 or state == 4 then
367 center(" -------------- ",math.floor(h/2)+1)
368 center(" -------------- ",math.floor(h/2)+4)
369 end
370 sleep(0.2)
371 if state == 5 then
372 local bal = api.balance(data.username)
373 if type(bal) == "number" and bal >= tonumber(price) then
374 local amount = math.floor(bal/price+0.00001)
375 repeat
376 sleep(1)
377 until api.send(data.username,data.password,data.vault,bal)
378 dispenseItem(sel[1],amount)
379 data.products[sel[1]].price = data.products[sel[1]].price * (1+price_change_magnitude)
380 break
381 end
382 end
383 end
384 end
385 local function cancelUiFunction()
386 while true do
387 local e,c,x,y = os.pullEvent("monitor_touch")
388 local monW,monH = m.getSize()
389 if y > monH-2 then break end
390 end
391 end
392 parallel.waitForAny(vendingFunction,cancelUiFunction)
393 end
394 break
395 end
396 end
397 end
398end
399
400--/ Admin UI /--
401local function lockoutScreen()
402 while true do
403 term.setBackgroundColor(colors.black)
404 term.setTextColor(colors.white)
405 term.clear()
406 term.setCursorPos(1,1)
407 print(data.name.." | Locked")
408 write("> ")
409 local passInput = read("*")
410 if sha256.sha256(passInput) == data.lockoutPW then
411 print("Welcome")
412 sleep(1)
413 break
414 else
415 printError("Invalid Password")
416 sleep(2)
417 end
418 end
419end
420local function adminUI()
421 -- Chest Warning
422 if not chest then
423 term.setBackgroundColor(colors.black)
424 term.clear()
425 term.setCursorPos(1,1)
426 print("Dynamic Shop")
427 printError("DANGER")
428 printError("You are not storing your valueables in a chest.")
429 printError("this means your shop is vulnerable to theft.")
430 print()
431 printError("Place a chest on top of your turtle and place your valueables in it.")
432 sleep(5)
433 end
434
435 -- Initialization
436 term.setBackgroundColor(colors.gray)
437 term.clear()
438 term.setCursorPos(2,2)
439 term.setTextColor(colors.lightGray)
440 write("Dynamic Shop - Boot")
441 term.setCursorPos(2,4)
442 term.setTextColor(colors.white)
443 write("Initializing...")
444 if #errors > 0 then
445 term.setCursorPos(2,6)
446 write("!! Fatal Error(s) Encountered:")
447 for i,v in pairs(errors) do
448 term.setCursorPos(2,7+i)
449 write("- "..v)
450 end
451 print()
452 print()
453 print(" Startup aborted.")
454 if m and m.isColor() then
455 m.setTextScale(0.5)
456 m.setBackgroundColor(colors.blue)
457 m.clear()
458 m.setTextColor(colors.white)
459 m.setCursorPos(2,2)
460 m.write("0xCE2752129 | INIT ERR")
461 for i,v in pairs(errors) do
462 m.setCursorPos(2,3+i)
463 m.write(string.upper(v))
464 end
465 end
466 sleep(20)
467 os.reboot()
468 else
469 term.setCursorPos(2,5)
470 write("Complete!")
471 end
472 local w,h = term.getSize()
473 -- First Time Setup
474 if init then
475 -- Setup Stage 1
476 term.setBackgroundColor(colors.black)
477 term.clear()
478 term.setCursorPos(2,2)
479 term.setTextColor(colors.white)
480 write("Dynamic Shop | Setup 1/4")
481 term.setCursorPos(2,4)
482 term.setTextColor(colors.lightGray)
483 write("Shop Name")
484 term.setTextColor(colors.gray)
485 term.setCursorPos(2,6)
486 write("Select a display name to be")
487 term.setCursorPos(2,7)
488 write("shown on the display.")
489 term.setCursorPos(2,h-1)
490 write("> ")
491 term.setTextColor(colors.white)
492 data.name = read()
493 -- Setup Stage 2
494 term.setBackgroundColor(colors.black)
495 term.clear()
496 term.setCursorPos(2,2)
497 term.setTextColor(colors.white)
498 write("Dynamic Shop | Setup 2/4")
499 term.setCursorPos(2,4)
500 term.setTextColor(colors.lightGray)
501 write("Shop Username")
502 term.setTextColor(colors.gray)
503 term.setCursorPos(2,6)
504 write("The name of this economy account")
505 term.setCursorPos(2,7)
506 write("Case sensitive")
507 term.setCursorPos(2,h-1)
508 write("> ")
509 term.setTextColor(colors.white)
510 data.username = read()
511 -- Setup Stage 3
512 term.setBackgroundColor(colors.black)
513 term.clear()
514 term.setCursorPos(2,2)
515 term.setTextColor(colors.white)
516 write("Dynamic Shop | Setup 3/4")
517 term.setCursorPos(2,4)
518 term.setTextColor(colors.lightGray)
519 write("Vault Username")
520 term.setTextColor(colors.gray)
521 term.setCursorPos(2,6)
522 write("The account to send any earnings to")
523 term.setCursorPos(2,7)
524 write("Case sensitive")
525 term.setCursorPos(2,h-1)
526 write("> ")
527 term.setTextColor(colors.white)
528 data.vault = read()
529 -- Setup Stage 4
530 local selection = 1
531 while true do
532 term.setBackgroundColor(colors.gray)
533 term.clear()
534 term.setCursorPos(2,2)
535 term.setTextColor(colors.white)
536 write("Dynamic Shop | Setup 4/4")
537 term.setCursorPos(2,4)
538 term.setTextColor(colors.lightGray)
539 write("Accent Color")
540 term.setCursorPos(2,6)
541 local options = {}
542 for i,v in pairs(colors) do
543 if type(v) == "number" and v ~= colors.gray then
544 options[#options+1] = v
545 end
546 end
547 if term.isColor() then
548 for i,v in pairs(options) do
549 term.setBackgroundColor(v)
550 write(" ")
551 end
552 term.setCursorPos((selection*2),7)
553 term.setBackgroundColor(colors.gray)
554 term.setTextColor(colors.white)
555 write("^^")
556 else
557 term.setCursorPos(2,7)
558 term.setTextColor(colors.white)
559 local option = options[selection]
560 for i,v in pairs(colors) do
561 if v == option then
562 option = i
563 end
564 end
565 write(string.upper(option))
566 end
567 term.setTextColor(colors.black)
568 term.setCursorPos(2,h-2)
569 write("<> Change Selection")
570 term.setCursorPos(2,h-1)
571 write("[Enter] Select Color")
572 local e,k = os.pullEvent('key')
573 if k == keys.right then
574 selection = selection + 1
575 if selection > 15 then selection = 15 end
576 elseif k == keys.left then
577 selection = selection - 1
578 if selection < 1 then selection = 1 end
579 elseif k == keys.enter then
580 data.color = options[selection]
581 break
582 end
583 end
584 -- Setup Completion
585 term.setBackgroundColor(colors.black)
586 term.clear()
587 term.setTextColor(colors.white)
588 term.setCursorPos(2,2)
589 write(">> setup")
590 term.setCursorPos(2,4)
591 write("registering account.. ")
592 sleep(1)
593 data.password = tostring(math.random(99999,9999999))
594 if api.register(data.username,data.password) then
595 write("success!")
596 else
597 write("failed!")
598 term.setCursorPos(2,6)
599 write("fatal error, restarting.")
600 sleep(2)
601 os.reboot()
602 end
603 term.setCursorPos(2,5)
604 write("building database.. ")
605 sleep(0.5)
606 data.products = {}
607 write('success!')
608 sleep(0.5)
609 term.setCursorPos(2,6)
610 write("saving data.. ")
611 sleep(1)
612 saveData()
613 write("success!")
614 term.setCursorPos(2,8)
615 write("setup complete!")
616 term.setCursorPos(2,9)
617 write("press any key")
618 os.pullEvent('key')
619 init = false
620 end
621
622 -- Lockout
623 if data.lockoutPW then
624 lockoutScreen()
625 end
626
627 -- Menu Functions
628 local function menu(options,ln)
629 local selection = 1
630 while true do
631 term.setBackgroundColor(colors.gray)
632 for i,v in pairs(options) do
633 term.setCursorPos(1,ln+i-1)
634 term.clearLine()
635 term.setCursorPos(2,ln+i-1)
636 if selection == i then
637 term.setTextColor(colors.white)
638 write("> "..v)
639 else
640 term.setTextColor(colors.lightGray)
641 write("| "..v)
642 end
643 end
644 local e,k = os.pullEvent("key")
645 if k == keys.up then
646 selection = selection - 1
647 if selection < 1 then
648 selection = #options
649 end
650 elseif k == keys.down then
651 selection = selection + 1
652 if selection > #options then
653 selection = 1
654 end
655 elseif k == keys.enter then
656 return selection
657 end
658 end
659 end
660 local function count(tbl)
661 local count = 0
662 for i,v in pairs(tbl) do
663 count = count + 1
664 end
665 return count
666 end
667 -- Routine
668 while true do
669 term.setBackgroundColor(colors.gray)
670 term.clear()
671 term.setBackgroundColor(colors.lightGray)
672 term.setCursorPos(2,1)
673 term.clearLine()
674 term.setCursorPos(2,1)
675 term.setTextColor(colors.black)
676 write(data.name)
677 local sel = menu({"Products ("..tostring(count(data.products))..")","Uncategorized ("..tostring(count(uncategorized))..")","Lockout","Shell"},3)
678 if sel == 1 then
679 term.setBackgroundColor(colors.gray)
680 term.clear()
681 term.setBackgroundColor(colors.lightGray)
682 term.setCursorPos(2,1)
683 term.clearLine()
684 term.setCursorPos(2,1)
685 term.setTextColor(colors.black)
686 write("Product List")
687 local choices = {"<- Return"}
688 local productids = {false}
689 for i,v in pairs(data.products) do
690 choices[#choices+1] = v.name
691 productids[#productids+1] = i
692 end
693 local sel = menu(choices,3)
694 if sel ~= 1 then
695 local id = productids[sel]
696 local product = data.products[id]
697 term.setBackgroundColor(colors.gray)
698 term.clear()
699 term.setBackgroundColor(colors.lightGray)
700 term.setCursorPos(2,1)
701 term.clearLine()
702 term.setCursorPos(2,1)
703 term.setTextColor(colors.black)
704 write(product.name)
705 term.setBackgroundColor(colors.gray)
706 term.setTextColor(colors.lightGray)
707 term.setCursorPos(2,3)
708 write("Price")
709 term.setCursorPos(2,4)
710 write("Start Price")
711 term.setCursorPos(14,3)
712 term.setTextColor(colors.white)
713 write(fixedTostring(math.floor(product.price*100)/100).." "..currency)
714 term.setCursorPos(14,4)
715 write(fixedTostring(product.start_price).." "..currency)
716 local sel = menu({"<- Return","Delete","Set Price"},7)
717 if sel == 2 then
718 data.products[id] = nil
719 saveData()
720 elseif sel == 3 then
721 term.setCursorPos(2,h-1)
722 term.setTextColor(colors.white)
723 write("> ")
724 local input = tonumber(read())
725 if input then
726 data.products[id].price = input
727 end
728 saveData()
729 end
730 end
731 elseif sel == 2 then
732 term.setBackgroundColor(colors.gray)
733 term.clear()
734 term.setBackgroundColor(colors.lightGray)
735 term.setCursorPos(2,1)
736 term.clearLine()
737 term.setCursorPos(2,1)
738 term.setTextColor(colors.black)
739 write("Uncategorized Items")
740 local choices = {"<- Return"}
741 for i,v in pairs(uncategorized) do
742 choices[#choices+1] = i
743 end
744 local sel = menu(choices,3)
745 if sel ~= 1 then
746 local id = choices[sel]
747 term.setBackgroundColor(colors.gray)
748 term.clear()
749 term.setBackgroundColor(colors.lightGray)
750 term.setCursorPos(2,1)
751 term.clearLine()
752 term.setCursorPos(2,1)
753 term.setTextColor(colors.black)
754 write("Create Product")
755 term.setBackgroundColor(colors.gray)
756 term.setTextColor(colors.lightGray)
757 term.setCursorPos(2,3)
758 write("Product Name")
759 term.setCursorPos(2,4)
760 write("Start Price")
761 term.setCursorPos(16,3)
762 term.setTextColor(colors.white)
763 local product = {}
764 product.name = read()
765 term.setCursorPos(16,4)
766 product.price = tonumber(read())
767 term.setCursorPos(16,5)
768 product.min_price = product.price
769
770 product.start_price = product.price
771 product.price_timer = 0
772
773 data.products[id] = product
774
775 term.setCursorPos(2,7)
776 if tonumber(product.price) and tonumber(product.min_price) then
777 saveData()
778 write("Product Created!")
779 else
780 write("Failed")
781 end
782 sleep(1.5)
783 end
784 elseif sel == 3 then
785 if data.lockoutPW then
786 lockoutScreen()
787 else
788 term.setBackgroundColor(colors.gray)
789 term.clear()
790 term.setBackgroundColor(colors.lightGray)
791 term.setCursorPos(2,1)
792 term.clearLine()
793 term.setCursorPos(2,1)
794 term.setTextColor(colors.black)
795 write("Set Lockout Password")
796 term.setBackgroundColor(colors.gray)
797 term.setCursorPos(2,3)
798 term.setTextColor(colors.white)
799 print("Enter your new password")
800 term.setCursorPos(2,4)
801 term.setTextColor(colors.lightGray)
802 write("> ")
803 local pass1 = read("*")
804 term.setCursorPos(2,5)
805 write("Confirm")
806 term.setCursorPos(2,6)
807 write("> ")
808 local pass2 = read("*")
809 term.setCursorPos(2,8)
810 term.setTextColor(colors.white)
811 if pass1 == pass2 then
812 data.lockoutPW = sha256.sha256(pass1)
813 write("Password set.")
814 saveData()
815 else
816 write("Passwords do not match")
817 end
818 sleep(2)
819 end
820 elseif sel == 4 then
821 term.setBackgroundColor(colors.black)
822 term.clear()
823 term.setCursorPos(1,1)
824 shell.run('shell')
825 end
826 end
827end
828
829--/ Kernel /--
830local function kernel()
831 parallel.waitForAny(shopRoutine,adminUI,invMgmt)
832end
833while true do
834 local ok,err = pcall(kernel)
835 if not ok and err ~= "Terminated" then
836 printError("Crashed: "..tostring(err))
837 sleep(5)
838 end
839end