This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Noiro's profile picture

[STABLE] MoveAPI - Reboot persist, coordinate tracking, smart movement

Started by Noiro, 08 August 2014 - 04:57 PM
Noiro #1
Posted 08 August 2014 - 06:57 PM
Move API
v1.31

NOTICE: This API is now released as stable with exception to the travel() function still being experimental. All else should be fine.
So, what is MoveAPI? Well, moveAPI is a full toolset allowing you to easily navigate/move and get your turtle around the map as smoothly as possible with as little code as possible. It offers everything from simple dig replacements which automatically handle falling sand/gravel/gravity blocks, to advanced customization moveTo() of specific coordinates using relative or specific. Want to say, "Eh, go to these coordinates and if something gets in the way, break it or attack it until it's not and keep going till you get there", you can!

How to use: When you download the program, just os.loadAPI("apiName"). It should download and be named 'move', but if you choose to rename it, you will import under that name, instead. Any functions you want to call MUST START WITH turtle.functionName() (yes, vanilla turtle functions have been overwritten while move is loaded.)
One thing to note, MoveAPI is setup so if you plan to use any of the GPS/coordinate tracking features, ALL TURTLE MOVEMENT COMMANDS in your programs must use move. As long as all programs running on the turtle import move, coordinates should always persist properly. Just don't get into the shell and type "go forward 3" or whatever because on next load it will wipe your GPS data due to inaccuracy.

Random note: coordinates are reboot/chunkload persistent so as long as you have a program using move as startup, move will always know where it is at. If you pick it up and place it back down, be sure to delete move's config file in /api/moveLoc. If the turtle's fuel changes by more than 1 when off, he will auto-reset upon re-import of move (coords will overwrite and store as 0,0,0,"north"). If you plan to place autoexecuting turtles back down, ensure your program running move uses turtle.setCoords() accordingly. The only time you may get some corruption of your coordinates is in the event of a server crash, the server not saving block locations properly, and move saving, thus putting him however many blocks back the server failed to. This can't be fixed on my end so: Try not to crash your server :P/>

Downloads
SpoilerStable
Stable v1.31 - 9QFxP4Ff for pastebin program

Beta
None atm

Planned Features for 1.33
-Turn optimization (turns in fastest route)
-Cleaning up param input for travel and moveTo to accept GPS and a little more dynamic stuffs
-Adding turtle.back to overwrite list (woops)
-Notice: I will be deprecating the function turtle.turnToDir() and switching it out with turtle.turnTo(), new version will give you a chance to switch everything over. 1.34 will not support turtle.turnToDir()
-Additionally, I will be removing collision handling from the feature list. After a little more introspection, I don't feel it fits within the scope of this project. I may create a pathfinding API later on down the line but for now, I'd like to limit moveAPI to just the movements provided.


Changelogs
Spoilerv1.32
-Fixed a couple minor bugs, sped up mining. Mostly bugfixes.
v1.31
-Fixed a tiny mishap with turtle.refuel()
-Optimized turtle.digDown() so it doesn't have the same lag-time the other dig's do waiting for things to fall (since they won't)
v1.3
-Persistence of holding coordinates through reboots
-Fixes to forward/up/down so they return false with obstructions
-Added navigate() for chunkload hacking around the map
-Cleaning up some old code in the the moveTo()'s, still need to do more of that, they're messy.
-travel() will pickup where it left off if server restarts and get to the destination once chunks reload.
-For travel(), moveTo's, you can pass in a table of x,y,z and dir (if you want) or pass in just x/y/z/dir by itself.
-For travel() and moveTo's, further options CAN be passed in to specify order of axis the turtle solves for. Just enter "x", "z", "y" (must include all three) in whatever order you want the turtle to nav

Documentation/How-To
SpoilerDigging
Spoilerdig()
-Pretty self-explanatory, digs in front (automatically handles sand/gravel)

digUp()
-Digs upwards, will handle sand/gravel falling

digDown()
-Same as turtle.dig(), here so you never have to use turtle.etc when executing similar commands.

NOTE: If you need vanilla digging mechanics for any reason (only mine just one block, no gravity blocks), use move.dig()/digUp/digDown() instead.

Movement
Spoilerforward([distance])
-Moves forward (1 forward if no arg given, will move x forward if an int provided)
–Returns false if something in the way

up([distance])
-Moves up (1 up if no arg given, will move x up if an int provided)
–Returns false if something in the way

down([distance])
-Moves down (1 forward if no arg given, will move x down if an int provided)
–Returns false if something in the way

fForward([distance])
-Moves forward (1 forward if no arg given, will move x forward if an int provided). Will break blocks in front and move if they are in way. Will attack monsters if they are in way.
–Returns false if unable to break block (ie. bedrock/warded block)

fDown([distance])
-Moves down (1 down if no arg given, will move x down if an int provided) Will break blocks in above and move if they are in way. Will attack monsters if they are in way.
–Returns false if unable to break block (ie. bedrock/warded block)

fUp([distance])
-Moves up (1 up if no arg given, will move x up if an int provided) Will break blocks in below and move if they are in way. Will attack monsters if they are in way.
–Returns false if unable to break block (ie. bedrock/warded block)

move(direction, distance)
-Moves in the given direction and removes objects if in the way (viable examples of dir are "north", "south", "east", "west")
–Returns false if something unbreakable in the way

Turning

turnLeft()
-Turns left, updates GPS dir

turnRight()
-Turns right, updates GPS dir

turnAround()
-Turns around, updates GPS dir

turnToDir(dir)
-Turns to direction specified (north, south, east, west <- As strings)

GPS/Location
SpoilerNote: Upon importing moveAPI for the first time, your coordinates will start as: 0,0,0,"north". This is for those who wish to build programs which only abide by relative coordinates more useful. (ie, going to starting location would be move.goto(0,0,0,"north")

setCoords(x,y,z,dir)
-Sets the coordinates to those provided (used for exact coordinate systems)

getCoords()
–Returns the x,y,z,dir of the turtle's current coordinates

getCoordsTbl()
–Returns the x,y,z,dir table (great for easily setting locations you can pass into moveTo and travel())

getX()
–Returns current X coordinate

getY()
–Returns current Y coordinate

getZ()
–Returns current Z coordinate

getDir()
–Returns current Direction

getFront()
–Returns x,y,z of space immediately in front of turtle

getFrontTbl()
–Returns table containing x,y,z of space immediately in front of turtle

Advanced Movement
SpoilerNote: moveTo() and travel() CAN utilize pathfinding. To deactivate it, move.setPathFinding(false). By doing this, at any obstacle the turtle cannot overcome, it will return false for that function, instead.

moveTo(x,y,z, , dir[axisCustomize if you want])
-Goes to the coordinates provided. If you enter 4 coordinate requirements into a table, you can pass the table in as replacement. Proper usage if using a coordinate table is:
–Returns true or false

  coords = {xInt, yInt, zInt, dirString}
  moveTo(coords)
or if you want to customize whether the turtle solves for which axis in which order (default is x, then y, then z)

  moveTo(xCoord, yCoord, zCoord, dir, "x", "z", "y") --Goes to specified coordinates, then follows x axis, then z axis, then y axis.
or

home = {0,0,0,"north"}
moveTo(home, "y","z","x") --Goes to coordinates in home table but follows y axis first, then z, then x to get there

fMoveTo(x,y,z, dir, [axisCustomize if you want])
-Goes to the coordinates provided. Digs/attacks things out of the way if needed. For further usage instructions, follow moveTo() instructions
–Returns false if cannot move.

move(direction, distance)
-Goes in the direction specified for the number of blocks specified (accepted directions are "north", "south", "east", "west")
–Returns false if cannot move.

navigate(x,y,z,dir)
-A chunkload hack used to move anywhere on a map regardless of loaded chunks. Requires turtle have a ChickenChunks chunkloader.
-!Notice: If the server reboots when the turtle is moving and no chunkloader is placed, the turtle will cease. If you have your programs auto-restart, just reexecute travel and you should be fine. Check your turtle has his loader, first before continuing (look up)
-Notice 2: I highly suggest you have the turtle navigate to a y-level out of range first (or just moveTo if that area will be loaded), THEN run your travel() to whereever. Less stuff to run into that way.
Example:

turtle.moveTo(turtle.getX(),120, turtle.getZ())
turtle.travel(location)

–Returns false if it gets stuck (warded blocks or bedrock, likely)

setChunkSlot(slotNum)
-Sets the slot the turtle will look for the chunkloader in.

setPathFinding(setting)
-Turns on or off pathfinding for moveTo and travel() (only two functions which utilize it). On by default.

Random
Spoilerrefuel(refuelAmount)
-Attempts to refuel from selected slot. Returns false if failed.


Credits
-Sangar who I found out (85% into this project), had made something extremely similar for an older version. Sangar, I am borrowing your awesome idea to use fuel-level checks to compare for persistence. Thank you, much!
-Inari in IRC: Your help in various questions I had (I learned as I went) was greatly appreciated (and your massive code condensation help).
-Random IRC/forum people I poked regarding various aspects of stuff, mostly about how the heck Lua does function table overwrites
Edited on 01 July 2015 - 12:13 PM
Cranium #2
Posted 08 August 2014 - 08:06 PM
Looks good so far. Let us know when you have some code, and we can put this in the programs section.
Noiro #3
Posted 08 August 2014 - 08:23 PM
Looks good so far. Let us know when you have some code, and we can put this in the programs section.
Tbh, the code is like 90% there, just need to finish testing a few functions, but I'll release once I get them shined up.
flaghacker #4
Posted 08 August 2014 - 09:01 PM
I suggest returning the amount of blocks already travelled when any of the moment functions fail.

So this is 100% reboot persistent? Nice!
Noiro #5
Posted 08 August 2014 - 09:11 PM
I suggest returning the amount of blocks already travelled when any of the moment functions fail.

So this is 100% reboot persistent? Nice!
Well, I will preface that with: It's the program calling move's job to restart itself on reboot, not move. But if your program does restart and call move, move will have your coordinates.

As for turning around, I'm sure that shouldn't be too hard for you to implement in your own programs. :)/> I don't think that'd be a good idea as a default option as most wouldn't want that.
Edited on 08 August 2014 - 07:17 PM
Win7yes #6
Posted 10 August 2014 - 04:49 PM
I think is

os.loadAPI("api Name")

and not

os.import("api Name")
Noiro #7
Posted 11 August 2014 - 02:53 AM
I think is

os.loadAPI("api Name")
and not

os.import("api Name")

Woops, thanks for catching that. I had a friend review the post and he was like, "Make sure you specify they have to import and use move.etc" So I kinda hastily threw that in there (though if you're going to be using an API, that should be common sense)
Sovietshark #8
Posted 12 August 2014 - 07:19 AM
You should make a spin-off of this and make a nuking application. Input current co-ordinates of the turtle then the destination it needs to go to (mining and digging on the way) before it places a nuke and lights it off.
Cranium #9
Posted 12 August 2014 - 06:27 PM
Like I was saying in IRC, I think you can clean up the documentation of the goto() function.

You can specify that the main arguments are as such:
goto(x, y, z, dir)
and then while explaining how to use it, you can mention that instead of separate values, you can pass a table of those values to the funtion. This would be an actual usage example, such as:
local home = {0, 0, 0, "north"}
goto(home)
My recommendation is that instead of listing the available arguments as goto([coordinateTable or x], [y], [z], [dir], [x/y/z, x/y/z, x/y/z]), you'd just list them as what I suggested earlier.
Noiro #10
Posted 13 August 2014 - 12:43 AM
You should make a spin-off of this and make a nuking application. Input current co-ordinates of the turtle then the destination it needs to go to (mining and digging on the way) before it places a nuke and lights it off.
If you like, the program would be REEAAALLY easy to make….


os.importAPI("move")
turtle.travel(nukeLocation)
turtle.up()
turtle.placeDown()
rs.setOutput("bottom", true)
sleep(.1)
rs.setOutput("bottom", false)
turtle.travel(home)

Tbh, the turtle may not survive that depending on range of the nuke.

Update Status: Testing - 98.3%

-Basic movement functions - tested
-moveTo and fMoveTo - tested
-Reboot Persistence - tested
-travel() - Works for the most partish, don't super rely on it quite yet
-collisionHandling() - Turn that on if you really don't have any other obstacle avoidance available, will do its best

In other news, the beta is released! When you guys test collisionHandling or travel() (specifically), keep an eye out. Most of the core forward/fFoward stuff should be perfectly fine along with moveTo and fMoveTo, travel() has and likely always will be a little experimental. And I did basic collision handling because bored so…yeah. If you were one of the zealous ones to download the first couple minutes I uploaded, redownload…I forgot to turn debug off XD
Edited on 26 August 2014 - 12:14 AM
Cranium #11
Posted 26 August 2014 - 02:38 AM
Moved to APIs on request.
Noiro #12
Posted 12 November 2014 - 12:15 PM
So….any feedback on this guys? Should I modify, keep it as-is, tips/tricks, suggestions?
Edited on 12 November 2014 - 11:15 AM
blackrabt #13
Posted 07 March 2015 - 12:42 PM
I really like this. Currently using it to cut out a lot of coding of custom paths for some turtles in a storage retrieval system. Great work! Love to see it keep going if you have the time and interest.
If I might suggest something, another moveTo method that will try to complete a movement in one direction, but if it encounters an obstacle and is not supposed to break blocks, it tries to move in another axis toward the destination and then returns to the blocked axis after it has made progress. Does that make sense?

Also if it were possible to use an existing rednet GPS setup to input the initial coordinates that would save some work with turtles that are frequently moved. I suppose the built in GPS does not supply facing, but setCoords((gps.locate), "west") would still be nice.
Edited on 07 March 2015 - 11:44 AM
Krutoy242 #14
Posted 28 March 2015 - 07:50 AM
Cool functions and stable work! Also, i like the idea of restoring coordinates if 1 fuel was consumed.

But i cant understand, why saveData() called after turn function?

turtle.turnLeft = function()
--Turns turtle left once and changes dir
turnLeft()
if dir == "north" then dir = "west"
elseif dir == "south" then dir = "east"
elseif dir == "west" then dir = "south"
elseif dir == "east" then dir = "north"
end
saveData()
end
If server restarting during rotation in progress, isnt new coordinates will be unsaved?

Also, I found, that you not redefine turtle.back() function. If this will be called manually, turtle will be lost.

And, i found small mistake on 752 line:

elseif data[5] > (turtle.getFuelLevel()-1) or data[5] < turtle.getFuelLevel() then
You already cheked for == fuel() and == fuel()+1 , so right comparsion should be

elseif data[5] > (turtle.getFuelLevel()+1) or data[5] < turtle.getFuelLevel() then
And after this, next code after else is unreachable.
Noiro #15
Posted 22 May 2015 - 05:06 PM
Cool functions and stable work! Also, i like the idea of restoring coordinates if 1 fuel was consumed.

But i cant understand, why saveData() called after turn function?

turtle.turnLeft = function()
--Turns turtle left once and changes dir
turnLeft()
if dir == "north" then dir = "west"
elseif dir == "south" then dir = "east"
elseif dir == "west" then dir = "south"
elseif dir == "east" then dir = "north"
end
saveData()
end
If server restarting during rotation in progress, isnt new coordinates will be unsaved?

Also, I found, that you not redefine turtle.back() function. If this will be called manually, turtle will be lost.

And, i found small mistake on 752 line:

elseif data[5] > (turtle.getFuelLevel()-1) or data[5] < turtle.getFuelLevel() then
You already cheked for == fuel() and == fuel()+1 , so right comparsion should be

elseif data[5] > (turtle.getFuelLevel()+1) or data[5] < turtle.getFuelLevel() then
And after this, next code after else is unreachable.

Thank you for looking it over. I am going to go back over and poke at some of the edits you mentioned. My only worry is that I'm uncertain on if the server reboots during a turn if the turn gets saved by CC the moment the turtle starts turning (in which case I should saveData() first, or if it will not save the state until it's finished so during a reboot, the turtle will go back to before it tried (my theory at the time)).

I am planning to pick this back up again and poke a couple extra things. I've had a lot going on in life recently so been busy, but with a new modpack I'm building and wanting to get my WorldEater program perfected (which uses move), I will be going back over some of the code. I was not even aware turtle.back() was even a thing. :o/>
Edited on 22 May 2015 - 03:07 PM
Noiro #16
Posted 01 July 2015 - 02:22 PM
I really like this. Currently using it to cut out a lot of coding of custom paths for some turtles in a storage retrieval system. Great work! Love to see it keep going if you have the time and interest.
If I might suggest something, another moveTo method that will try to complete a movement in one direction, but if it encounters an obstacle and is not supposed to break blocks, it tries to move in another axis toward the destination and then returns to the blocked axis after it has made progress. Does that make sense?

Also if it were possible to use an existing rednet GPS setup to input the initial coordinates that would save some work with turtles that are frequently moved. I suppose the built in GPS does not supply facing, but setCoords((gps.locate), "west") would still be nice.
In 1.34, I am changing up a little bit of code that handles how you input parameters into the navigation stuff. You should be able to pass a GPS location in as you specified. In 1.3.4, if you use turtle.setCoords(gps.locate()) and don't specify a facing, he will assume whatever direction he has as his facing is the right one. So if you pick him up and he's facing south and put him down, make sure he's facing south. Or just specify and ensure you put him down facing that dir. Essentially how the new parameters will work is that if you include a table in the parameters, it will assume any numbers in the table as coordinates and assign them in the order it gets them (first number it gets will be X, whether it is in a table or not), so if you wanted to you could:


xTable = {354}
turtle.moveTo(xTable, "y", "x", "south", "z", 13, 5)

That would say: "Go to coordinates: x:354, y:-13, z: 5, face south when you get there, then travel along the y axis first, then x, then z." Order will no longer matter in terms of where you place the variables, but order DOES matter relative to numbers and x,y,z axis order. In your case:

originalPos = gps.locate()
--Insert code to go do a thing
turtle.moveTo(originalPos, "east")
print("Hey, I'm back!")

Would work just fine. Though if I"m totally honest, I'm being a bit selfish in that half the reason I even am adding this is so you can pull stuff like:


--Locations
home = {0,0,0,"north","z","x","y"}
exitHome1 = {5,0,-6,"east","x","z","y"}
exitHome2 = {5,3,-6,"east","y","z","x"}
friendHouse = {-306,55,1522, "south"}

function goHome()
  turtle.moveTo(exitHome2)
  turtle.moveTo(exitHome1)
  turtle.moveTo(home)
end

function leaveHome()
  turtle.moveTo(exitHome1)
  turtle.moveTo(exitHome2)
end

--Here's the fun part
leaveHome()
turtle.travel(friendHouse)
--Insert code to fill his house with water (I'm a bad person)
goHome()

See how this code works? It essentially allows you to build locations and then make functions that essentially generate paths so the turtle can get around without hitting things. He enters into exit2 (which is likely the turtle entranceway), then moves down into exit1 (which is where he'll then go into his 'home' position), then go to home, this way, along with axis specifications, you have full control over how he gets where. :)/>/&amp;gt;
Edited on 01 July 2015 - 06:15 PM