Advertisement
buffsovernexus

Untitled

Nov 22nd, 2019
336
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.70 KB | None | 0 0
  1. --[[
  2.  
  3. FarmerBot v3.0.0
  4.  
  5. -- Banned Mods --
  6. Natura > This mod was not properly built in the sense that the bot cannot understand when crops are done growing.
  7. HarvestCraft > This mod does not work well with the learning system. I will keep it in, but it will struggle with any harvestcraft crops.
  8.  
  9. -- Instructions --
  10. 1) Place your bot on top of a chest, which is one space below the bottom-right of the farm.
  11. 2) Run this script.
  12. 3) Enter in how many rows there are (how many rows are to the left?)
  13. 4) Enter in how long each row is (how far does the bot have to go down the row)
  14. 5) Enter in what seed the bot will place on empty farmland.
  15.  
  16. -- Side Notes --
  17. ~ The bot will stop working properly if you do not give it more fuel.
  18. ~ The bot will dynamically learn new props from the mod list.
  19. ~ 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.
  20. ~ This script will give detailed information on each newly learned crop.
  21. ~ If you enter in 0 for Seed ID, the bot will plant any seed it has in its inventory.
  22.  
  23.  
  24. -- Future Plans --
  25. ~ The bot will communicate with an outside service (a designated script called FBDS) to handle crop and remote functionality.
  26.  
  27. -- Known Issues --
  28. ~ The bot will sometimes not learn crops properly (wont identify seeds) and will mess up that session.
  29. ]]--
  30.  
  31. -- This table is the "memory" of the bot.
  32. local botdata = {
  33. crops = {},
  34. cmds = {},
  35. mods = {},
  36. input = {},
  37. -- VERIFY: This is either true or false (true = success, false = fail)
  38. }
  39.  
  40. -- This table is meant to be sent to the DB.
  41. local botSendData = {
  42. learned = {},
  43. input = {},
  44. gps = {
  45. x = 0,
  46. y = 0,
  47. z = 0
  48. },
  49. request = "" -- This is the type of request for the DB to filter out (e.g. learn: Learned a new crop, now handle it.)
  50. }
  51.  
  52. --[[ handleModem()
  53.  
  54. Task: Allow the bot to remotely speak to a specific computer.
  55.  
  56. ]]--
  57. function handleModem()
  58. if rednet.isOpen("right") == false then
  59. rednet.open("right")
  60. end
  61. rednet.host("fbtpa", os.getComputerLabel())
  62. rednet.host("fbtp", os.getComputerLabel())
  63. end
  64.  
  65. handleModem()
  66.  
  67.  
  68. -- [[ START PLAYER INPUT ]]--
  69. local input = { rows = 0, length = 0, crop = 0, db = 0 }
  70.  
  71. function getUserInput()
  72. term.write("Enter number of rows (left): ")
  73. input.rows = tonumber(read())
  74. term.write("Enter in length of row (forward): ")
  75. input.length = tonumber(read())
  76. for k,v in pairs (botdata.crops) do
  77. print("#", v.id," - ", v.label)
  78. end
  79. term.write("Enter crop ID (or 0) for seeding: ")
  80. input.crop = tonumber(read())
  81. botdata.input = input
  82.  
  83. -- Send User Data to DB.
  84. botSendData.input = botdata.input
  85. botSendData.request = "input_send"
  86. rednet.send(input.db, textutils.serialize(botSendData), "fbtp")
  87. end
  88.  
  89. term.write("Enter in FarmBotDB ID: ")
  90. input.db = tonumber(read())
  91. botSendData.request = "input_ask"
  92. rednet.send(input.db, textutils.serialize(botSendData), "fbtp")
  93.  
  94. local senderId, response, protocol = rednet.receive("fbtp")
  95. response = textutils.unserialize(response)
  96.  
  97. -- Determine if previous instructions exist.
  98. if response.verify.isSuccess then
  99. term.clear()
  100. print(" Previous Task")
  101. print("---------------------------------------")
  102. print("Rows: " .. response.input.rows)
  103. print("Length: " .. response.input.length)
  104. print("Crop Seed ID: " .. response.input.crop)
  105. print(" ")
  106. term.write("Use this (y/n)? ")
  107. local answer = read()
  108. if string.lower(answer) == "y" then
  109. input = response.input
  110. botdata.input = response.input
  111. print("SUCCESS: Using previous task.")
  112. else
  113. getUserInput()
  114. end
  115. else
  116. getUserInput()
  117. end
  118. -- [[ END PLAYER INPUT ]]--
  119.  
  120. -- [[ SEND GPS COORDINATES ]]--
  121. local x, y, z = gps.locate()
  122.  
  123. -- Ensure the GPS location worked.
  124. if not x then
  125. print("ERROR: GPS location not found. Try again.")
  126. else
  127. botSendData.gps.x = x
  128. botSendData.gps.y = y
  129. botSendData.gps.z = z
  130. botSendData.request = "gps_send"
  131.  
  132. -- Send to DB.
  133. rednet.send(botdata.input.db, textutils.serialize(botSendData), "fbtp")
  134.  
  135. -- Wait for DB to respond.
  136. local senderId, response, protocol = rednet.receive("fbtp")
  137. response = textutils.unserialize(response)
  138. if response.verify.isSuccess then
  139. print("SUCCESS: Sending GPS location.")
  140. else
  141. print("ERROR: Unable to save GPS location.")
  142. end
  143. end
  144. --[[ END SEND GPS COORDINATES ]]--
  145.  
  146. --[[ getLatestCropList()
  147.  
  148. Task: Get the latest crop list from the DB.
  149.  
  150. ]]--
  151. function getLatestCropList()
  152. botSendData.request = "latest"
  153. rednet.send(botdata.input.db, textutils.serialize(botSendData), "fbtp")
  154. local senderId, response, protocol = rednet.receive("fbtp")
  155. response = textutils.unserialize(response)
  156. botdata.crops = response.crops
  157. botdata.mods = response.mods
  158. end
  159.  
  160. --[[ refuel()
  161.  
  162. Task: To check for any fuel in the slots and consume it.
  163.  
  164. ]]--
  165. function refuel()
  166. for i = 16,1,-1 do
  167. turtle.select(i)
  168. turtle.refuel( math.ceil(turtle.getItemCount()) )
  169. end
  170. end
  171.  
  172. --[[ dropItems()
  173.  
  174. Task: Select each item and put the item into the chest below.
  175.  
  176. ]]--
  177. function dropItems()
  178. for i = 16,1,-1 do
  179. turtle.select(i)
  180. turtle.dropDown()
  181. end
  182. end
  183.  
  184. --[[ fixBlock()
  185.  
  186. Task: Place a seed crop based on <input.crop>, or any seed if no specific crop.
  187.  
  188. ]]--
  189. function fixBlock()
  190. turtle.digDown()
  191. -- If the crop is 0, then the user wants the bot to place any seeds in the inventory.
  192. if input.crop == 0 then
  193. for k,v in pairs(botdata.crops) do
  194. if hasSeeds(v.id) then
  195. turtle.placeDown()
  196. break
  197. end
  198. end
  199. else
  200. -- The user has selected a specific crop.
  201. if hasSeeds(input.crop) then
  202. turtle.placeDown()
  203. end
  204. end
  205. end
  206.  
  207. -- 3.0 Function: Have the bot learn crops instead of manually entering them.
  208. function learnCrop(cropBlock)
  209. -- Determine if the block is in any of the mods we listed.
  210. for i = 1, getSize(botdata.mods) do
  211. if string.match( string.lower(cropBlock.name) , string.lower(botdata.mods[i]) ) then
  212. -- Step 1: Get the current list of crops and make the ID.
  213. local id = getSize(botdata.crops) + 1
  214. local cropName = cropBlock.name
  215.  
  216. -- Step 1b: Learn the maturity...
  217. local maturity = 7
  218. local metadata = 0
  219. if cropBlock ~= nil then metadata = cropBlock.metadata end
  220.  
  221. -- Step 2: Break the block to find the seed.
  222. turtle.digDown()
  223. -- Bug: Wait for all of the inventories.
  224. os.sleep(3);
  225. local unknown = {}
  226. for i = 1, 16 do
  227. local data = turtle.getItemDetail(i)
  228. --Look through each inventory space to find the unknown crop
  229. local isKnown = false
  230. for k,v in pairs(botdata.crops) do
  231. if data ~= nil then
  232. -- The crop is known, therefore skip it.
  233. if data.name == v.seed then
  234. isKnown = true
  235. end
  236. end
  237. end
  238.  
  239. -- If we do not know, then continue
  240. if isKnown == false then
  241. local checkDuplicates = false
  242. -- Check if data is already in unknown (no duplicates)
  243. if data ~= nil then
  244. for j=1, getSize(unknown) do
  245. if unknown[j].name == data.name then
  246. checkDuplicates = true
  247. end
  248. end
  249. end
  250.  
  251. if checkDuplicates == false then
  252. unknown[getSize(unknown) + 1] = data
  253. end
  254. end
  255. end
  256.  
  257. -- Step 3: Find the seed using the unknown blocks in the turtle.
  258. -- Quick Logic: If only one new item is found, then that is the seed.
  259. -- Other quick logic: If more than one (probably 2 at most) then check for 'seed' in text.
  260. local seedName = ""
  261. -- I don't know why it's here, but we'll keep it.
  262. getSize(unknown);
  263. if getSize(unknown) == 1 then
  264. seedName = unknown[1].name
  265. else
  266. for i=1,getSize(unknown) do
  267. if string.match( string.lower(unknown[i].name) , string.lower("%seed%") ) then
  268. seedName = unknown[i].name
  269. break
  270. end
  271. end
  272. end
  273.  
  274. -- Bug? Make sure seedName is filled. Otherwise, get the last thing to be added and call it a day.
  275. if string.len( seedName ) == 0 then
  276. seedName = unknown[getSize(unknown) - 1];
  277. end
  278.  
  279. -- Step 4: Enter in new crop to list of crops.
  280. local crop = { id = id, mature = maturity, name = cropName, seed = seedName, label = cropName, metadata = metadata }
  281.  
  282. -- Step 5: Add crop to cropdata.
  283. botSendData.learned = crop
  284. botSendData.request = "learn"
  285. rednet.send(input.db, textutils.serialize(botSendData), "fbtp")
  286.  
  287. -- Step 6: Wait for updated list from DB.
  288. local senderId, response, protocol = rednet.receive("fbtp")
  289. response = textutils.unserialize(response)
  290.  
  291. -- Step 7: Update the list to our bot.
  292. botdata.crops = response.crops
  293.  
  294. if response.verify.isSuccess then
  295. print(">> NEW CROP <<")
  296. print("Crop: ", crop.name)
  297. print("Seed:" , crop.seed)
  298. print("Maturity: ", crop.mature)
  299. else
  300. print(">> FAILED CROP <<")
  301. print("Crop: ", crop.name)
  302. end
  303.  
  304. -- Step 5: Replace seed.
  305. if hasSeeds(id) then
  306. turtle.placeDown()
  307. end
  308.  
  309. unknown = {};
  310. end
  311. end
  312.  
  313. end
  314.  
  315. --[[ Helper Functions ]]--
  316. function getSize(tbl)
  317. local count = 0
  318. if tbl == nil then return count end
  319. for _ in pairs(tbl) do count = count + 1 end
  320. return count
  321. end
  322. function isGrown(row, length, current, expected)
  323. if current == expected then
  324. return true
  325. end
  326. return false
  327. end
  328. function hasSeeds(id)
  329. for k,v in pairs(botdata.crops) do
  330. if v.id == id then
  331. for i = 1, 16 do
  332. local data = turtle.getItemDetail(i)
  333. if data ~= nil then
  334. if data.name == v.seed then
  335. turtle.select(i)
  336. return true
  337. end
  338. end
  339. end
  340. end
  341. end
  342. return false
  343. end
  344. --[[ End Helper Functions ]]--
  345. function handleFarming()
  346. --[[ START FARMING TASK ]]--
  347.  
  348. -- Adjust bot placement.
  349. os.sleep(1)
  350. if turtle.detectDown() then
  351. print("WARN: Fixing orientation.")
  352. turtle.up()
  353. os.sleep(1)
  354. turtle.forward()
  355. os.sleep(1)
  356. end
  357.  
  358. -- Make sure the bot has a list to grab from.
  359. getLatestCropList()
  360.  
  361.  
  362. while true do
  363. for i = 1, input.rows do
  364. for j = 1, input.length do
  365. -- Determine if there is a crop below the bot.
  366. if turtle.detectDown() then
  367. local success, data = turtle.inspectDown()
  368. if success then
  369. -- Bot AI: Determine if the crop is known, or if its even a crop.
  370. local isKnown = false
  371. if data.name ~= "minecraft:cobblestone" or data.name ~= "minecraft:water" or data.name ~= "minecraft:cobblestone_slab" then
  372. for k,v in pairs(botdata.crops) do
  373. if data.name == v.name then
  374. isKnown = true
  375. if isGrown(i,j,data.metadata,v.mature) then
  376. -- The crop is fully matured. Need to break crop and replace with seed.
  377. turtle.digDown()
  378. turtle.suckDown()
  379. local curpos = turtle.getSelectedSlot();
  380. if hasSeeds(v.id) then
  381. turtle.placeDown()
  382. end
  383. -- Legend: "Reset the positioning of the selected slot so bot can stack crops properly."
  384. turtle.select(curpos)
  385. end
  386. end
  387. end
  388. -- If the crop is unknown, have the bot attempt to learn the crop.
  389. if isKnown == false then
  390. learnCrop(data)
  391. end
  392. end
  393. end
  394. else
  395. -- The block below does not have a crop. Attempt to remedy this.
  396. fixBlock()
  397. end
  398.  
  399. -- Go forward one to continue.
  400. if j < input.length then
  401. turtle.forward()
  402. end
  403. end
  404.  
  405. -- Done reviewing the row. Now move to new row.
  406. local isEven = i % 2 == 0
  407. if isEven == false then
  408. turtle.turnLeft()
  409. turtle.forward()
  410. turtle.turnLeft()
  411. else
  412. turtle.turnRight()
  413. turtle.forward()
  414. turtle.turnRight()
  415. end
  416. end
  417.  
  418. -- Goal: Attempt to go back to start.
  419.  
  420. -- Logic: If the number of rows to the left are even, then the bot will end up on a different side.
  421. if input.rows % 2 == 1 then
  422. for k = 1, input.length do
  423. turtle.forward()
  424. end
  425. else
  426. turtle.turnLeft()
  427. turtle.turnLeft()
  428. turtle.forward()
  429. end
  430. turtle.turnLeft()
  431. for l = 1, input.rows do
  432. turtle.forward()
  433. end
  434. turtle.turnLeft()
  435.  
  436. -- Drop items in hopper below.
  437. turtle.down()
  438.  
  439. -- Attempt to refuel if refueling is setup.
  440. os.sleep(2)
  441. refuel()
  442. -- Drop all items in the inventory into chest below.
  443. dropItems()
  444. -- Wait for crops to grow a bit.
  445. os.sleep(300)
  446.  
  447. -- 3.0.0: Grab the latest crop list.
  448. getLatestCropList()
  449.  
  450. -- Reset bot position for next harvest.
  451. turtle.up()
  452. turtle.forward()
  453. end
  454. --[[ END FARMING TASK ]]--
  455. end
  456.  
  457. function handleCommands()
  458.  
  459. while true do
  460. local senderId, response, protocol = rednet.receive("fbtpa")
  461.  
  462. response = textutils.unserialize(response)
  463.  
  464. -- Check if any pending commands.
  465. if getSize(response.cmds) > 0 then
  466. -- Run the command.
  467. for i=1,getSize(response.cmds) do
  468. shell.run(response.cmds[i])
  469. end
  470. end
  471. end
  472.  
  473. end
  474.  
  475. handleFarming()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement