· 7 years ago · Nov 16, 2018, 12:28 AM
1--[[
2Valvates library for cordanite management and stuff.
3If you have an idea for feature make an issue or
4Create a pull request if you're a coder.
5A lot of stuff here is unfinished so
6Be careful and tell me how to make it better :DD
7
8WARNING!
9Since the turtle writes his coordanites to a file you should
10run fs.delete(t.coordsfile) when your program finishes!
11if you don't then his coords will get all screwed up if he moved without updating his coords
12
13If you're using gps you can manually set coords and then update them
14heres some untested example code
15
16t = require("val_api")
17t.x, t.y, t.z = gps.locate(0.5)
18In this example orientation is still set to north by default,
19if you want to find orientation you'll need code that compares coords
20after you move, i might add this later but for now its up to you! ;)
21
22TODO:
23 Write saved positions to a file and read from it on startup.
24 Add automatic gps support, maybe with a bool config variable to turn it on or off.
25
26Here is an index that i think some programmers will find useful
27
28function t.dumpCoords()
29returns the current coordanaites in a table \w orientation
30
31function t.inTable(value, table)
32Checks if a value is in a table.
33
34function t.cleanInventory()
35Tries to clean the turtles inventory by-
36throwing out unwanted items.
37defined in the t.unWantedItems list.
38
39function t.writeToFile(msg, file, mode)
40valid modes are "a", append and "w", overwrite
41simply writes to the file in args and cleanly closes it afterwards.
42
43function t.log(msg, msg_debug_level)
44logs messages, 5 levels starting at 0.
454: [DEBUG]
463: [INFO]
472: [WARNING]
481: [ERROR]
490: [FATAL] (Will terminate the program after logging)
50Will not log the message if t.debug_level is less then msg_debug_level.
51
52function t.savePositionsToFile()
53Writes t.saved_positions to t.posfile
54
55function t.init()
56this function gets the correct coordanites from the t.coordsfile file.
57if the file does not exist, it will create it and initalize the coordanites to 0,0,0,0
58
59--]]
60local t = {}
61
62t.debug_level = 4
63
64t.logfile = "val_lib.log"
65t.coordsfile = "coords"
66t.posfile = "savedPositions"
67
68local file -- Used for file management lower down
69t.saved_positions = {}
70
71t.blocks_dug = 0
72
73-- How to increment depending on the orientation
74local zDiff = {
75 [0] = -1,
76 [1] = 0,
77 [2] = 1,
78 [3] = 0
79}
80
81local xDiff = {
82 [0] = 0,
83 [1] = 1,
84 [2] = 0,
85 [3] = -1
86}
87
88-- Needed for human readable input/output
89t.orientations = {
90 [0] = "north",
91 [1] = "east",
92 [2] = "south",
93 [3] = "west"
94}
95
96-- Unwanted items for clean inventory function.
97t.unWantedItems = {
98 "minecraft:cobblestone",
99 "minecraft:stone",
100 "minecraft:flint",
101 "minecraft:dirt",
102 "minecraft:sandstone",
103 "minecraft:sand"
104}
105
106function t.dumpCoords()
107 return {
108 x = t.x,
109 y = t.y,
110 z = t.z,
111 orientation = t.orientation,
112 }
113end
114
115function t.inTable(value, table)
116 for key, v in ipairs(table) do
117 if value == value then
118 return true
119 end
120 end
121 -- if its not in the table then
122 return false
123end
124
125function t.cleanInventory()
126 local item
127 local prevSlot = turtle.getSelectedSlot()
128
129 for i=1,16 do
130 item = turtle.getItemDetail(i)
131 -- Makes sure item exists to avoid nil errors.
132 if item and t.inTable(item.name, t.unWantedItems) then
133 turtle.select(i)
134 turtle.dropDown(item.count) -- Drops all of the unwanted item
135 end
136 turtle.select(prevSlot) -- Leave no trace!
137 end
138end
139
140function t.writeToFile(msg, file, mode)
141 -- Function used by logging function.
142 -- i felt it was cleaner this way.
143 if mode == nil then
144 mode = "a" -- By default append
145 end
146
147 if file == nil then
148 t.log("[DEBUG] file to write to is nil, defaulting to "..t.logfile)
149 file = t.logfile -- default
150 end
151
152 if msg == nil then
153 t.log("[ERROR] msg is nil in function t.writeToFile")
154 return
155 end
156
157 file = io.open(file, mode)
158
159 if file == nil then
160 t.log("[ERROR] Failed to open "..file, 0)
161 return
162 end
163
164 file:write(msg.."\n") -- Adds newline
165 file:close()
166end
167
168function t.log(msg, msg_debug_level)
169 -- Logging function
170
171 if msg_debug_level == nil then
172 t.writeToFile("[WARNING] msg_debug_level is nil, defaulting to level 3 message info.", t.logfile)
173 -- As a param this is already local.
174 msg_debug_level = 3
175 end
176
177 if msg_debug_level <= t.debug_level then
178 t.writeToFile(msg, t.logfile)
179 end
180 -- Terminate the program if the message level is fatal.
181 if msg_debug_level == 0 then
182 print("Fatal error, read "..t.logfile.." for more info.")
183 error()
184 end
185end
186
187-- Get coords from file if file does not exist create one and set coords to 0,0,0,0
188function t.init()
189 local coords
190 local contents
191 if t.coordsfile == nil then
192 t.log("[ERROR] t.coordsfile is nil", 1)
193 t.log("[WARNING] Without a coords file persistance will fail", 2)
194 return -- Breaks from this function
195 end
196
197 if not fs.exists(t.coordsfile) then
198 t.log("[WARNING] t.coordsfile does not exist", 2)
199 t.log("[INFO] Creating coordsfile...", 3)
200 -- Creates coords file with 0,0,0,0 as values.
201 t.writeToFile(textutils.serialize(
202 {
203 x = 0,
204 y = 0,
205 z = 0,
206 orientation = 0
207 }),
208 t.coordsfile,
209 "w")
210
211 if not fs.exists(t.coordsfile) then
212 t.log("[FATAL] Failed to create "..t.coordsfile, 0)
213 end
214 end
215
216 file = io.open(t.coordsfile, "r") -- Opens coordsfile for reading.
217 if file == nil then
218 t.log("[FATAL] Failed to open coordsfile, file is nil", 0)
219 end
220
221 contents = file:read("*all")
222 file:close()
223
224 if contents == nil then
225 t.log("[FATAL] Failed to read file contents", 0)
226 end
227
228 t.log("[DEBUG] Read file contents, trying to unserialize it", 4)
229 coords = textutils.unserialize(contents)
230 if type(coords) ~= "table" then
231 t.log("[FATAL] failed to unserialize contents, coords is not a table", 0)
232 end
233
234 -- Sets coordanites
235 t.log("[DEBUG] Got coordanites from file, they are\n"..textutils.serialize(coords), 4)
236 t.x = coords.x
237 t.y = coords.y
238 t.z = coords.z
239
240 -- Sets orientation
241 t.orientation = coords.orientation
242
243 -- Not going to return a value since i will just change the varables.
244end
245
246-- Saves coordanites to file
247local function saveCords()
248 t.log("[DEBUG] saveCords function called.", 4)
249 t.log("[DEBUG] t.x = "..t.x.." t.y = "..t.y.." t.z = "..t.z.." t.orientation = "..t.orientation, 4)
250 local c = {
251 x = t.x,
252 y = t.y,
253 z = t.z,
254 orientation = t.orientation
255 }
256 c = textutils.serialize(c)
257
258 t.log("[DEBUG] Updating "..t.coordsfile.."\n"..c, 4)
259 t.writeToFile(c, t.coordsfile, "w")
260end
261
262local function orientationToNumber(orientationStr)
263 -- Turns an orientation string into an Orientation number.
264 for i=0,#t.orientations do
265 if orientationStr == t.orientations[i] then
266 return i
267 end
268 end
269end
270
271-- Turns an orientation number into an t.orientation string.
272local function orientationToString(orientationInt)
273 -- Checks to see if orientationInt is a number
274 if type(orientationInt) ~= "number" then
275 t.log("[FATAL] orientationInt is not a number", 0)
276 end
277 if orientations[orientationInt] then
278 return t.orientations[orientationInt]
279 else
280 print("[FATAL] orientation is invalid", 0)
281 print("orientationInt = "..orientationInt)
282 end
283end
284
285-- Turning functions
286function t.turnRight()
287 turtle.turnRight()
288 -- This "magic" math adds one to t.orientation unless t.orientation is 3, then it moves to 0.
289 -- This could also be done with an if statement but this is cleaner imo
290 t.orientation = (t.orientation + 1) % 4
291 saveCords()
292end
293
294function t.turnLeft()
295 turtle.turnLeft()
296 t.orientation = (t.orientation - 1) % 4
297 saveCords()
298end
299
300-- Looks to a direction, can be passed a string or a number
301function t.look(direction)
302 -- makes sure the value passed is valid.
303 if type(direction) == "string" then
304 direction = orientationToNumber(direction)
305 elseif type(direction) ~= "number" then
306 error("Direction is not a number")
307 end
308
309 -- Thanks to Incin for this bit of code :)
310 if direction == t.orientation then return end
311
312 if (direction - t.orientation) % 2 == 0 then
313 t.turnLeft()
314 t.turnLeft()
315 elseif (direction - t.orientation) % 4 == 1 then
316 t.turnRight()
317 else
318 t.turnLeft()
319 end
320end
321
322function t.forward()
323 t.log("[DEBUG] t.forward called", 4)
324
325 if turtle.forward() then
326 t.log("[DEBUG] turtle.forward() returned true, changing coords...", 4)
327 -- Change t.x and t.z coords
328 t.x = t.x + xDiff[t.orientation]
329 t.z = t.z + zDiff[t.orientation]
330
331 t.log("[DEBUG] Calling saveCords from t.forward", 4)
332 saveCords()
333 return true
334 else
335 -- If he failed to move return false and don't change the coords.
336 t.log("[DEBUG] turtle.forward() returned false", 4)
337 return false
338 end
339end
340
341function t.up()
342 t.log("[DEBUG] t.up function called", 4)
343 if turtle.up() then
344 t.y = t.y + 1
345 t.log("[DEBUG] Trying to save coords to file after going up", 4)
346 saveCords()
347 return true
348 else
349 return false
350 end
351end
352
353function t.down()
354 if turtle.down() then
355 t.y = t.y - 1
356 saveCords()
357 return true
358 else
359 return false
360 end
361end
362
363function t.digDown()
364 if turtle.digDown() then
365 t.blocks_dug = t.blocks_dug + 1
366 return true
367 else
368 return false
369 end
370end
371function t.dig()
372 if turtle.dig() then
373 t.blocks_dug = t.blocks_dug + 1
374 return true
375 else
376 return false
377 end
378end
379function t.digUp()
380 if turtle.digUp() then
381 t.blocks_dug = t.blocks_dug + 1
382 return true
383 else
384 return false
385 end
386end
387
388-- This function saves the turtles position so it can be returned to later.
389function t.saveCurrentPos(name)
390 if type(name) ~= "string" then
391 error("Position name must be a string.")
392 end
393
394 -- Creates a new table entry with "name" key
395 t.saved_positions[name] = {
396 x = t.x,
397 y = t.y,
398 z = t.z,
399 orientation = t.orientation
400 }
401end
402
403function t.savePositionsToFile()
404 t.writeToFile(textutils.serialize(t.saved_positions), t.posfile, "w")
405end
406
407function t.getPos()
408 if fs.exists(t.posfile) then
409 file = io.open(t.posfile, "r")
410 t.saved_positions = textutils.unserialize(file:read("*all")())
411 file:close()
412 else
413 error("No file to get positions from.")
414 end
415end
416
417function t.gotoPos(name)
418 if t.saved_positions[name] == nil then error("[ERROR] t.saved_positions["..name.."] is nil") end
419 for i,v in ipairs(t.saved_positions[name]) do print(i,v) end -- temp
420
421 t.goto(t.saved_positions[name].x, t.saved_positions[name].y, t.saved_positions[name].z, t.saved_positions[name].orientation)
422end
423
424-- Careful this breaks blocks.
425function t.goto(xTarget, yTarget, zTarget, orientationTarget)
426 if not xTarget or not yTarget or not zTarget or not orientationTarget then
427 t.log("[DEBUG] Here are all the params for the goto function:", 4)
428 t.log("xTarget="..xTarget.."yTarget="..yTarget.."zTarget="..zTarget.."orientationTarget="..orientationTarget, 4)
429 error("t.goto Can\"t travel to nil!, read logs for more info")
430 end
431 -- Moves to t.y
432 while yTarget < t.y do
433 t.digDown()
434 t.down()
435 end
436
437 while yTarget > t.y do
438 t.digUp()
439 t.up()
440 end
441
442 -- Turns to correct t.orientation then moves forward until its at the right t.x cord
443 if xTarget < t.x then
444 t.look("west")
445 while xTarget < t.x do
446 t.dig()
447 t.forward()
448 end
449 end
450
451 if xTarget > t.x then
452 t.look("east")
453 while xTarget > t.x do
454 t.dig()
455 t.forward()
456 end
457 end
458
459 -- Turns to correct t.orientation then moves forward until its at the right t.z cord
460 if zTarget < t.z then
461 t.look("north")
462 while zTarget < t.z do
463 t.dig()
464 t.forward()
465 end
466 end
467 if zTarget > t.z then
468 t.look("south")
469 while zTarget > t.z do
470 t.dig()
471 t.forward()
472 end
473 end
474 -- Look to correct orientation
475 t.look(orientationTarget)
476end
477-- Because its not defined at the top
478t.init()
479return t