· 5 months ago · May 01, 2025, 04:20 PM
1-- Misc Useful Functions
2-- Required by most other programs
3
4
5-------------------------------------------
6-- |¯¯] || |¯¯] \\// /\ |¯\ [¯¯] --
7-- | ] ||_ | ] >< | | | / ][ --
8-- || |__] |__] //\\ |||| || [__] --
9-------------------------------------------
10
11local log_file = "log.txt"
12local options_file = "flex_options.cfg"
13
14-- Defaults; can be changed in config file
15local modem_channel = 6464
16local name_color
17if term.isColor() then
18 name_color = "yellow"
19else
20 name_color = "lightGray"
21end --if/else
22
23
24function getPeripheral(name)
25 local x,sides
26 sides = { "top", "bottom", "left",
27 "right", "front", "back" }
28 local periph = {}
29 for x=1,#sides do
30 if peripheral.getType(sides[x]) == name then
31 periph[#periph+1] = sides[x]
32 end --if
33 end --for
34 return periph
35end --function
36
37
38local modem
39local hasModem = false
40local x = getPeripheral("modem")
41if #x > 0 then
42 hasModem = true
43 modem = peripheral.wrap(x[1])
44 modem.open(modem_channel)
45end --if
46
47function modemOff()
48 local x = getPeripheral("modem")
49 if #x > 0 then
50 modem.close(modem_channel)
51 end --if
52end --function
53
54
55local file
56if not fs.exists(log_file) then
57 file = fs.open(log_file,"w")
58 file.close()
59end --if
60
61
62
63function optionsExport()
64 if fs.exists(options_file) then
65 fs.delete(options_file)
66 end
67 local file
68 while file == nil do
69 file = fs.open(options_file,"w")
70 end
71 file.writeLine("# Flex API Options File #\n")
72 file.writeLine("modem_channel="
73 ..tostring(modem_channel))
74 file.writeLine("name_color="..name_color.."\n")
75 file.close()
76 return true
77end --function
78
79
80function optionsImport()
81 if not fs.exists(options_file) then
82 return false
83 end
84 local file
85 while file == nil do
86 file = fs.open(options_file, "r")
87 end
88
89 local x = file.readLine()
90 while x ~= nil do
91 if string.find(x,"modem_channel")==1 then
92 modem_channel = tonumber(string.sub(x,15))
93 elseif string.find(x,"name_color")==1 then
94 name_color = string.sub(x,12)
95 end --if/else
96 x = file.readLine()
97 end --while
98
99 file.close()
100 return true
101end --function
102
103
104if not optionsImport() then
105 optionsExport()
106end --if
107
108
109
110--==============================--
111
112
113-- Inventory Condense
114function condense(n)
115 if n == nil then n = 1 end
116 n = math.floor(n)
117 if n < 1 or n > 16 then
118 n = 1
119 end --if
120
121 local x,y,slot
122 slot = turtle.getSelectedSlot()
123 for x=n+1,16 do
124 if turtle.getItemCount(x) > 0 then
125
126 for y=n,x-1 do
127 if turtle.getItemCount(y) == 0 or
128 turtle.getItemDetail(x)["name"] ==
129 turtle.getItemDetail(y)["name"] and
130 turtle.getItemSpace(y) > 0 then
131 turtle.select(x)
132 turtle.transferTo(y)
133 end --if
134 if turtle.getItemCount(x) == 0 then
135 break
136 end --if
137 end --for
138
139 end --if
140 end --for
141 turtle.select(slot)
142end --function
143
144
145-- Round n to p decimal places
146function round(n,p)
147 if p == nil then p = 0 end
148 n = n*math.pow(10,p)
149 local m = n - math.floor(n)
150 if m < 0.5 then
151 return math.floor(n) / math.pow(10,p)
152 else
153 return math.ceil(n) / math.pow(10,p)
154 end --if/else
155end --function
156
157
158-- Number to String
159-- Optionally a max length if not an integer
160function tostr(num,len)
161 num = tostring(num)
162 local sci = ""
163
164 local e = string.find(num,"e")
165 if e ~= nil then
166 -- Separate exponent from number
167 sci = string.sub(num,e,-1)
168 num = string.sub(num,1,e-1)
169 end --if
170
171 if string.find(num,"%.") ~= nil then
172 -- Remove extra zeroes from decimal
173 while string.sub(num,string.len(num)) == "0" do
174 num = string.sub(num,1,string.len(num)-1)..""
175 end --while
176 end --if
177
178 if string.sub(num,-1) == "." then
179 -- If all trailing zeroes are gone, erase decimal point
180 num = string.sub(num,1,-2)..""
181 end --if
182
183 if len == nil then
184 -- If no max length specified
185 return num..sci..""
186 end --if
187
188 while string.len(num) + string.len(sci) > len do
189 -- If too long, cut off a decimal digit
190 num = string.sub(num,1,-2)..""
191 end --while
192
193 return num..sci..""
194
195end --function
196
197
198-- Evaluate Expression
199function eval(expression)
200 local solution, err = loadstring(
201 "return "..expression)
202 if err then error(err,2) end
203 local sol = pcall(solution)
204 if not sol then
205 error("Invalid Expression",2)
206 end
207 return solution()
208end --function
209
210
211-- Press any Key
212function getKey()
213 local event, key_code = os.pullEvent("key")
214 return key_code
215end --function
216function keyPress() return getKey() end
217
218
219
220
221-------------------------------
222-- [¯¯] |¯¯] \\// [¯¯] --
223-- || | ] >< || --
224-- || |__] //\\ || --
225-------------------------------
226-- /¯] /¯\ || /¯\ |¯\ --
227-- | [ | O | ||_ | O | | / --
228-- \_] \_/ |__] \_/ | \ --
229-------------------------------
230
231hexchars = "0123456789ABCDEF"
232
233-- Start with named value, get hex char
234function getHex(x)
235 if x == nil then
236 error("Number expected, got nil", 2)
237 end
238 x = round(math.log(x)/math.log(2))
239 if x < 0 or x > 15 then
240 error("Invalid color number", 2)
241 end --if
242 return string.sub(hexchars,x+1,x+1)
243end --function
244
245-- Start with hex char, get named value
246function getVal(x)
247 local z = string.find(hexchars,x)
248 if z == nil then return nil end
249 return math.pow(2,z-1)
250end --function
251
252local send_depth, print_depth = 0, 0
253
254
255
256-------------------------------
257-- Multicolor Print Function --
258-------------------------------
259
260function printColors(message,textColor)
261 local x,y,z,t,skip,margin
262 local xmax,ymax = term.getSize()
263 local oldColor = term.getTextColor()
264 if textColor == nil then
265 textColor = oldColor
266 else
267
268 end --if
269
270 margin = ""
271 for x=1,print_depth do
272 margin = margin.." "
273 end --for
274
275 if type(message) == "table" then
276 if print_depth == 0 then
277 printColors("#0{")
278 end --if
279 print_depth = print_depth + 1
280
281 for x,y in pairs(message) do
282 if type(y) == "table" then
283 printColors(margin.." "..tostring(x).." #0= {",textColor)
284 printColors(y,textColor)
285 else
286 printColors(margin.." "..tostring(x).." #0= #"..
287 getHex(textColor)..tostring(y),textColor)
288 end --if/else
289 end --for
290
291 print_depth = print_depth - 1
292 printColors(margin.."#0}")
293 return
294
295 end --if
296
297 if type(textColor) == "number" then
298 message = "#"..getHex(textColor)
299 ..tostring(message)
300 end --if
301
302 for t=1,string.len(message) do
303
304 skip = false
305 while string.sub(message,t,t) == "#" and
306 not skip do
307
308 -- Found legit "#"
309 if string.sub(message,t+1,t+1) == "#" then
310 message = string.sub(message,1,t)..
311 string.sub(message,t+2)..""
312 skip = true
313
314 else
315 textColor = getVal(string.sub(message,t+1,t+1))
316
317 if textColor == nil then
318 textColor = colors.white
319 end --if
320
321 -- This bit clears out # escapes
322 if t == 1 then
323 message = string.sub(message,3)..""
324 elseif t < string.len(message) then
325 message = string.sub(message,1,t-1)..
326 string.sub(message,t+2)..""
327 elseif t == string.len(message) then
328 message = string.sub(message,1,t-1)..""
329 end --if/else
330
331 end --if
332
333 if t > string.len(message) then
334 break
335 end --if
336
337 end --while (is escape char)
338
339 if t > string.len(message) then
340 break
341 end --if
342
343 -- Actually Print Character
344 x,y = term.getCursorPos()
345 term.setTextColor(textColor)
346
347 if textColor == colors.gray then
348 --term.setBackgroundColor(colors.lightGray)
349
350 elseif textColor == colors.black then
351 term.setBackgroundColor(colors.lightGray)
352
353 end --if/else
354 term.write(string.sub(message,t,t))
355 term.setBackgroundColor(colors.black)
356
357 if t >= string.len(message) then
358 break
359 end --if
360
361 -- Loop Around to Next Row
362 xmax,ymax = term.getSize()
363 if string.sub(message,t,t) == "\n" or x >= xmax then
364 x = 1
365 if y < ymax-1 then
366 y = y + 1
367 else
368 print("")
369 end --if/else
370 else
371 x = x + 1
372 end --if/else
373 term.setCursorPos(x,y)
374
375 end --for
376
377 term.setTextColor(oldColor)
378 print("")
379
380end --function
381
382
383
384------------------------------
385-- Print/Broadcast Function --
386------------------------------
387
388function send(message,textColor)
389 local x,y,z,id,nameColor
390 local oldColor = term.getTextColor()
391
392 local margin = ""
393 for x=1,send_depth do
394 margin = margin.." "
395 end --for
396
397 if type(message) == "table" then
398 if send_depth == 0 then
399 send("#0{")
400 end --if
401 send_depth = send_depth + 1
402
403 for x,y in pairs(message) do
404 if type(y) == "table" then
405 send(margin.." "..tostring(x).." #0= {",textColor)
406 send(y,textColor)
407 else
408 send(margin.." "..tostring(x).." #0= #"
409 ..getHex(textColor)..tostring(y),textColor)
410 end --if/else
411 end --for
412
413 send_depth = send_depth - 1
414 send(margin.."#0}")
415 return
416
417 end --if
418
419
420 if message == nil then
421 message = "nil"
422 end --if
423
424 message = tostring(message)
425 if textColor == nil then
426 textColor = colors.white
427 end --if
428 nameColor = eval("colors."..name_color)
429
430 printColors(message)
431
432 file = fs.open(log_file,"a")
433 file.writeLine(message)
434 file.close()
435
436 if hasModem then
437 id = "#"..getHex(nameColor)..
438 tostring(os.getComputerID()).."#0"
439
440 if os.getComputerLabel() ~= nil then
441 id = id.."|#"..getHex(nameColor)..
442 os.getComputerLabel().."#0"
443 end --if
444
445 id = id..": #"..getHex(textColor)..
446 message..""
447
448 modem.transmit(modem_channel,
449 modem_channel+1,id)
450 sleep(0.1)
451 end --if (hasModem)
452
453 term.setTextColor(oldColor)
454 sleep(0.02)
455end --function (print/broadcast)
456
457
458--================================--
459
460
461args = {...}
462
463if args[1]=="color" or args[1]=="colors" then
464 z = ""
465 for x=0,15 do
466 y = string.sub(hexchars,x+1,x+1)..""
467 z = z.."#"..y..y.."#0 "
468 end --for
469 printColors(z)
470 return
471
472elseif args[1] == "edit" then
473 shell.run("edit "..options_file)
474 optionsImport()
475
476end --if/else
477
478
479
480-------------------------------------------
481-- /¯¯] |¯¯] [¯¯] |¯\ /\ [¯¯] /\ --
482--| [¯| | ] || | | | | || | | --
483-- \__| |__] || |_/ |||| || |||| --
484-------------------------------------------
485
486
487function getBlock(dir)
488 dir = dir or "fwd"
489 local block,meta
490
491 if dir=="fwd" then
492 block,meta = turtle.inspect()
493 elseif dir=="up" then
494 block,meta = turtle.inspectUp()
495 elseif dir=="down" then
496 block,meta = turtle.inspectDown()
497 end
498
499 if block then
500 block = meta["name"]
501 meta = meta["metadata"]
502 return block,meta
503 else
504 return "minecraft:air",nil
505 end --if
506
507end --function
508
509function getBlockUp()
510 return getBlock("up")
511end
512
513function getBlockDown()
514 return getBlock("down")
515end
516
517
518function isBlock(key,dir)
519 if type(key) == "string" then
520 key = { key }
521 end --if
522 if type(key) ~= "table" then
523 error("Expected string or table, got "
524 ..type(key), 2)
525 return false
526 end --if
527
528 local block = getBlock(dir)
529 local x
530 for x=1,#key do
531
532 if string.find(key[x],":") ~= nil then
533 if block == key[x] then
534 return true
535 end --if
536
537 else
538 if string.find(block,key[x]) ~= nil then
539 return true
540 end --if
541
542 end --if/else
543 end --for
544
545 return false
546end --function
547
548function isBlockUp(key)
549 return isBlock(key, "up")
550end
551
552function isBlockDown(key)
553 return isBlock(key, "down")
554end
555
556
557
558local fluid = { "air", "water", "lava",
559 "acid", "blood", "poison" }
560
561function isFluid(dir)
562 return isBlock(fluid, "fwd")
563end
564
565function isFluidUp()
566 return isBlock(fluid, "up")
567end
568
569function isFluidDown()
570 return isBlock(fluid, "down")
571end
572
573
574
575function isItem(key,slot)
576 if key == nil then return false end
577
578 local slot_old = turtle.getSelectedSlot()
579 if type(slot) ~= "number" then
580 slot = slot_old
581 end --if
582
583 if type(key) == "table" then
584 local x
585 for x=1,#key do
586 if isItem(key[x],slot) then
587 return true
588 end --if
589 end --for
590 return false
591 end --if
592
593 if turtle.getItemCount(slot) == 0 then
594 return false
595 end --if
596
597 local name = turtle.getItemDetail(slot)["name"]
598
599 return ( string.find(name,key) ~= nil )
600end --function
601
602
603