Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- FarmerBot v3.0.0
- -- Banned Mods --
- Natura > This mod was not properly built in the sense that the bot cannot understand when crops are done growing.
- HarvestCraft > This mod does not work well with the learning system. I will keep it in, but it will struggle with any harvestcraft crops.
- -- Instructions --
- 1) Place your bot on top of a chest, which is one space below the bottom-right of the farm.
- 2) Run this script.
- 3) Enter in how many rows there are (how many rows are to the left?)
- 4) Enter in how long each row is (how far does the bot have to go down the row)
- 5) Enter in what seed the bot will place on empty farmland.
- -- Side Notes --
- ~ The bot will stop working properly if you do not give it more fuel.
- ~ The bot will dynamically learn new props from the mod list.
- ~ The bot will refuel automatically if it runs into a fuel source (like feeding it a lava bucket in a hopper) before it goes again.
- ~ This script will give detailed information on each newly learned crop.
- ~ If you enter in 0 for Seed ID, the bot will plant any seed it has in its inventory.
- -- Future Plans --
- ~ The bot will communicate with an outside service (a designated script called FBDS) to handle crop and remote functionality.
- -- Known Issues --
- ~ The bot will sometimes not learn crops properly (wont identify seeds) and will mess up that session.
- ]]--
- -- This table is the "memory" of the bot.
- local botdata = {
- crops = {},
- cmds = {},
- mods = {},
- input = {},
- -- VERIFY: This is either true or false (true = success, false = fail)
- }
- -- This table is meant to be sent to the DB.
- local botSendData = {
- learned = {},
- input = {},
- gps = {
- x = 0,
- y = 0,
- z = 0
- },
- request = "" -- This is the type of request for the DB to filter out (e.g. learn: Learned a new crop, now handle it.)
- }
- --[[ handleModem()
- Task: Allow the bot to remotely speak to a specific computer.
- ]]--
- function handleModem()
- if rednet.isOpen("right") == false then
- rednet.open("right")
- end
- rednet.host("fbtpa", os.getComputerLabel())
- rednet.host("fbtp", os.getComputerLabel())
- end
- handleModem()
- -- [[ START PLAYER INPUT ]]--
- local input = { rows = 0, length = 0, crop = 0, db = 0 }
- function getUserInput()
- term.write("Enter number of rows (left): ")
- input.rows = tonumber(read())
- term.write("Enter in length of row (forward): ")
- input.length = tonumber(read())
- for k,v in pairs (botdata.crops) do
- print("#", v.id," - ", v.label)
- end
- term.write("Enter crop ID (or 0) for seeding: ")
- input.crop = tonumber(read())
- botdata.input = input
- -- Send User Data to DB.
- botSendData.input = botdata.input
- botSendData.request = "input_send"
- rednet.send(input.db, textutils.serialize(botSendData), "fbtp")
- end
- term.write("Enter in FarmBotDB ID: ")
- input.db = tonumber(read())
- botSendData.request = "input_ask"
- rednet.send(input.db, textutils.serialize(botSendData), "fbtp")
- local senderId, response, protocol = rednet.receive("fbtp")
- response = textutils.unserialize(response)
- -- Determine if previous instructions exist.
- if response.verify.isSuccess then
- term.clear()
- print(" Previous Task")
- print("---------------------------------------")
- print("Rows: " .. response.input.rows)
- print("Length: " .. response.input.length)
- print("Crop Seed ID: " .. response.input.crop)
- print(" ")
- term.write("Use this (y/n)? ")
- local answer = read()
- if string.lower(answer) == "y" then
- input = response.input
- botdata.input = response.input
- print("SUCCESS: Using previous task.")
- else
- getUserInput()
- end
- else
- getUserInput()
- end
- -- [[ END PLAYER INPUT ]]--
- -- [[ SEND GPS COORDINATES ]]--
- local x, y, z = gps.locate()
- -- Ensure the GPS location worked.
- if not x then
- print("ERROR: GPS location not found. Try again.")
- else
- botSendData.gps.x = x
- botSendData.gps.y = y
- botSendData.gps.z = z
- botSendData.request = "gps_send"
- -- Send to DB.
- rednet.send(botdata.input.db, textutils.serialize(botSendData), "fbtp")
- -- Wait for DB to respond.
- local senderId, response, protocol = rednet.receive("fbtp")
- response = textutils.unserialize(response)
- if response.verify.isSuccess then
- print("SUCCESS: Sending GPS location.")
- else
- print("ERROR: Unable to save GPS location.")
- end
- end
- --[[ END SEND GPS COORDINATES ]]--
- --[[ getLatestCropList()
- Task: Get the latest crop list from the DB.
- ]]--
- function getLatestCropList()
- botSendData.request = "latest"
- rednet.send(botdata.input.db, textutils.serialize(botSendData), "fbtp")
- local senderId, response, protocol = rednet.receive("fbtp")
- response = textutils.unserialize(response)
- botdata.crops = response.crops
- botdata.mods = response.mods
- end
- --[[ refuel()
- Task: To check for any fuel in the slots and consume it.
- ]]--
- function refuel()
- for i = 16,1,-1 do
- turtle.select(i)
- turtle.refuel( math.ceil(turtle.getItemCount()) )
- end
- end
- --[[ dropItems()
- Task: Select each item and put the item into the chest below.
- ]]--
- function dropItems()
- for i = 16,1,-1 do
- turtle.select(i)
- turtle.dropDown()
- end
- end
- --[[ fixBlock()
- Task: Place a seed crop based on <input.crop>, or any seed if no specific crop.
- ]]--
- function fixBlock()
- turtle.digDown()
- -- If the crop is 0, then the user wants the bot to place any seeds in the inventory.
- if input.crop == 0 then
- for k,v in pairs(botdata.crops) do
- if hasSeeds(v.id) then
- turtle.placeDown()
- break
- end
- end
- else
- -- The user has selected a specific crop.
- if hasSeeds(input.crop) then
- turtle.placeDown()
- end
- end
- end
- -- 3.0 Function: Have the bot learn crops instead of manually entering them.
- function learnCrop(cropBlock)
- -- Determine if the block is in any of the mods we listed.
- for i = 1, getSize(botdata.mods) do
- if string.match( string.lower(cropBlock.name) , string.lower(botdata.mods[i]) ) then
- -- Step 1: Get the current list of crops and make the ID.
- local id = getSize(botdata.crops) + 1
- local cropName = cropBlock.name
- -- Step 1b: Learn the maturity...
- local maturity = 7
- local metadata = 0
- if cropBlock ~= nil then metadata = cropBlock.metadata end
- -- Step 2: Break the block to find the seed.
- turtle.digDown()
- -- Bug: Wait for all of the inventories.
- os.sleep(3);
- local unknown = {}
- for i = 1, 16 do
- local data = turtle.getItemDetail(i)
- --Look through each inventory space to find the unknown crop
- local isKnown = false
- for k,v in pairs(botdata.crops) do
- if data ~= nil then
- -- The crop is known, therefore skip it.
- if data.name == v.seed then
- isKnown = true
- end
- end
- end
- -- If we do not know, then continue
- if isKnown == false then
- local checkDuplicates = false
- -- Check if data is already in unknown (no duplicates)
- if data ~= nil then
- for j=1, getSize(unknown) do
- if unknown[j].name == data.name then
- checkDuplicates = true
- end
- end
- end
- if checkDuplicates == false then
- unknown[getSize(unknown) + 1] = data
- end
- end
- end
- -- Step 3: Find the seed using the unknown blocks in the turtle.
- -- Quick Logic: If only one new item is found, then that is the seed.
- -- Other quick logic: If more than one (probably 2 at most) then check for 'seed' in text.
- local seedName = ""
- -- I don't know why it's here, but we'll keep it.
- getSize(unknown);
- if getSize(unknown) == 1 then
- seedName = unknown[1].name
- else
- for i=1,getSize(unknown) do
- if string.match( string.lower(unknown[i].name) , string.lower("%seed%") ) then
- seedName = unknown[i].name
- break
- end
- end
- end
- -- Bug? Make sure seedName is filled. Otherwise, get the last thing to be added and call it a day.
- if string.len( seedName ) == 0 then
- seedName = unknown[getSize(unknown) - 1];
- end
- -- Step 4: Enter in new crop to list of crops.
- local crop = { id = id, mature = maturity, name = cropName, seed = seedName, label = cropName, metadata = metadata }
- -- Step 5: Add crop to cropdata.
- botSendData.learned = crop
- botSendData.request = "learn"
- rednet.send(input.db, textutils.serialize(botSendData), "fbtp")
- -- Step 6: Wait for updated list from DB.
- local senderId, response, protocol = rednet.receive("fbtp")
- response = textutils.unserialize(response)
- -- Step 7: Update the list to our bot.
- botdata.crops = response.crops
- if response.verify.isSuccess then
- print(">> NEW CROP <<")
- print("Crop: ", crop.name)
- print("Seed:" , crop.seed)
- print("Maturity: ", crop.mature)
- else
- print(">> FAILED CROP <<")
- print("Crop: ", crop.name)
- end
- -- Step 5: Replace seed.
- if hasSeeds(id) then
- turtle.placeDown()
- end
- unknown = {};
- end
- end
- end
- --[[ Helper Functions ]]--
- function getSize(tbl)
- local count = 0
- if tbl == nil then return count end
- for _ in pairs(tbl) do count = count + 1 end
- return count
- end
- function isGrown(row, length, current, expected)
- if current == expected then
- return true
- end
- return false
- end
- function hasSeeds(id)
- for k,v in pairs(botdata.crops) do
- if v.id == id then
- for i = 1, 16 do
- local data = turtle.getItemDetail(i)
- if data ~= nil then
- if data.name == v.seed then
- turtle.select(i)
- return true
- end
- end
- end
- end
- end
- return false
- end
- --[[ End Helper Functions ]]--
- function handleFarming()
- --[[ START FARMING TASK ]]--
- -- Adjust bot placement.
- os.sleep(1)
- if turtle.detectDown() then
- print("WARN: Fixing orientation.")
- turtle.up()
- os.sleep(1)
- turtle.forward()
- os.sleep(1)
- end
- -- Make sure the bot has a list to grab from.
- getLatestCropList()
- while true do
- for i = 1, input.rows do
- for j = 1, input.length do
- -- Determine if there is a crop below the bot.
- if turtle.detectDown() then
- local success, data = turtle.inspectDown()
- if success then
- -- Bot AI: Determine if the crop is known, or if its even a crop.
- local isKnown = false
- if data.name ~= "minecraft:cobblestone" or data.name ~= "minecraft:water" or data.name ~= "minecraft:cobblestone_slab" then
- for k,v in pairs(botdata.crops) do
- if data.name == v.name then
- isKnown = true
- if isGrown(i,j,data.metadata,v.mature) then
- -- The crop is fully matured. Need to break crop and replace with seed.
- turtle.digDown()
- turtle.suckDown()
- local curpos = turtle.getSelectedSlot();
- if hasSeeds(v.id) then
- turtle.placeDown()
- end
- -- Legend: "Reset the positioning of the selected slot so bot can stack crops properly."
- turtle.select(curpos)
- end
- end
- end
- -- If the crop is unknown, have the bot attempt to learn the crop.
- if isKnown == false then
- learnCrop(data)
- end
- end
- end
- else
- -- The block below does not have a crop. Attempt to remedy this.
- fixBlock()
- end
- -- Go forward one to continue.
- if j < input.length then
- turtle.forward()
- end
- end
- -- Done reviewing the row. Now move to new row.
- local isEven = i % 2 == 0
- if isEven == false then
- turtle.turnLeft()
- turtle.forward()
- turtle.turnLeft()
- else
- turtle.turnRight()
- turtle.forward()
- turtle.turnRight()
- end
- end
- -- Goal: Attempt to go back to start.
- -- Logic: If the number of rows to the left are even, then the bot will end up on a different side.
- if input.rows % 2 == 1 then
- for k = 1, input.length do
- turtle.forward()
- end
- else
- turtle.turnLeft()
- turtle.turnLeft()
- turtle.forward()
- end
- turtle.turnLeft()
- for l = 1, input.rows do
- turtle.forward()
- end
- turtle.turnLeft()
- -- Drop items in hopper below.
- turtle.down()
- -- Attempt to refuel if refueling is setup.
- os.sleep(2)
- refuel()
- -- Drop all items in the inventory into chest below.
- dropItems()
- -- Wait for crops to grow a bit.
- os.sleep(300)
- -- 3.0.0: Grab the latest crop list.
- getLatestCropList()
- -- Reset bot position for next harvest.
- turtle.up()
- turtle.forward()
- end
- --[[ END FARMING TASK ]]--
- end
- function handleCommands()
- while true do
- local senderId, response, protocol = rednet.receive("fbtpa")
- response = textutils.unserialize(response)
- -- Check if any pending commands.
- if getSize(response.cmds) > 0 then
- -- Run the command.
- for i=1,getSize(response.cmds) do
- shell.run(response.cmds[i])
- end
- end
- end
- end
- handleFarming()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement