SimpleBeniFarm.lua

426 lines · 13.0 KB

Open raw

==================================================

Copy & run

wget https://perlytiara.github.io/turtles.tips/raw/programs/SimpleBeni/SimpleBeniFarm.lua
1-- ==================================================
2-- Thank you for using Beni's Farm Script!
3-- ==================================================
4--------------------------------------------------
5-- CONFIGURATION VARIABLES
6--------------------------------------------------
7local fuelSuckCount = 10 -- Number of fuel items (e.g., coal) to suck at start.
8local lowFuelThreshold = fuelSuckCount * 8
9
10--------------------------------------------------
11-- GLASS PANE COLOR SETUP
12--------------------------------------------------
13local args = {...}
14local glassColor = args[1] or "green"
15local targetGlassPane = "minecraft:" .. glassColor .. "_stained_glass_pane"
16--------------------------------------------------
17-- CLEAR CONSOLE
18term.clear()
19term.setCursorPos(1, 1)
20--------------------------------------------------
21print("Using " .. glassColor .. " stained glass pane for positioning.")
22
23--------------------------------------------------
24-- POSITIONING ROUTINE
25--------------------------------------------------
26local function positionTurtle()
27 local positioned = false
28 local attemptCounter = 0
29
30 while not positioned do
31 attemptCounter = attemptCounter + 1
32
33 local successDown, dataDown = turtle.inspectDown()
34 if successDown and dataDown.name == "minecraft:water" then
35 local successFront, dataFront = turtle.inspect()
36 if successFront and dataFront.name == "minecraft:chest" then
37 print("Position OK.")
38 positioned = true
39 else
40 -- If there's water below, but no chest in front, keep trying to move/turn.
41 if successFront then
42 if dataFront.name == "minecraft:air" then
43 turtle.forward()
44 elseif dataFront.name == "minecraft:glass" or dataFront.name == "minecraft:glass_pane" then
45 turtle.turnLeft()
46 elseif dataFront.name == targetGlassPane then
47 turtle.down()
48 else
49 turtle.forward()
50 end
51 else
52 turtle.forward()
53 end
54 end
55 else
56 -- No (or wrong) water below; keep searching
57 local successFront, dataFront = turtle.inspect()
58 if successFront then
59 if dataFront.name == "minecraft:air" then
60 turtle.forward()
61 elseif dataFront.name == "minecraft:glass" or dataFront.name == "minecraft:glass_pane" then
62 turtle.turnLeft()
63 elseif dataFront.name == targetGlassPane then
64 turtle.down()
65 else
66 turtle.forward()
67 end
68 else
69 turtle.forward()
70 end
71 end
72
73 -- If we’ve been trying for a while, warn the user.
74 if attemptCounter > 20 and not positioned then
75 print("WARNING: Turtle is not finding water below + chest in front!")
76 print("Ensure your farm setup has:")
77 print(" - Still water directly beneath the turtle.")
78 print(" - A chest directly in front of the turtle.")
79 print(" - The correct color stained glass pane above that chest.")
80 print(" - A fuel chest to the right of the turtle if it needs refueling.")
81 print("Retrying...")
82 sleep(10)
83 attemptCounter = 0
84 end
85 end
86end
87
88--------------------------------------------------
89-- FUEL CHECK ROUTINE
90--------------------------------------------------
91local function fuelCheck()
92 local fuel = turtle.getFuelLevel()
93 if fuel < lowFuelThreshold then
94 print("Fuel low (" .. fuel .. "); refueling...")
95 turtle.turnRight() -- Face refuel Ender Chest.
96 turtle.suck(fuelSuckCount)
97 for slot = 1, 16 do
98 turtle.select(slot)
99 turtle.refuel()
100 end
101 turtle.turnLeft() -- Restore original facing.
102 else
103 print("Fuel level sufficient (" .. fuel .. ").")
104 end
105end
106
107--------------------------------------------------
108-- DEPOSIT OPERATIONS
109--------------------------------------------------
110local function depositOperations()
111 -- Deposit the entire inventory into the chest in front.
112 for slot = 1, 16 do
113 turtle.select(slot)
114 turtle.drop()
115 end
116 print("Inventory deposited.")
117end
118
119--------------------------------------------------
120-- INVENTORY MANAGEMENT HELPERS
121--------------------------------------------------
122local function isInventoryFull()
123 for slot = 1, 16 do
124 if turtle.getItemDetail(slot) == nil then
125 return false
126 end
127 end
128 return true
129end
130
131local function organizeSeeds(cropBlock)
132 -- We only organize seeds for wheat and beetroots (which use dedicated slots)
133 local seedType, dedicatedSlot
134 if cropBlock == "minecraft:wheat" then
135 seedType = "minecraft:wheat_seeds"
136 dedicatedSlot = 1
137 elseif cropBlock == "minecraft:beetroots" then
138 seedType = "minecraft:beetroot_seeds"
139 dedicatedSlot = 4
140 else
141 return -- No organization for carrots or potatoes.
142 end
143
144 turtle.select(dedicatedSlot)
145 local dedicatedItem = turtle.getItemDetail(dedicatedSlot)
146 local space = 0
147 if dedicatedItem then
148 space = 64 - dedicatedItem.count -- Assume a stack size of 64.
149 else
150 space = 64
151 end
152
153 for slot = 1, 16 do
154 if slot ~= dedicatedSlot then
155 turtle.select(slot)
156 local detail = turtle.getItemDetail(slot)
157 if detail and detail.name == seedType then
158 if space > 0 then
159 local count = detail.count
160 local transferCount = math.min(count, space)
161 turtle.transferTo(dedicatedSlot, transferCount)
162 turtle.select(dedicatedSlot)
163 local newDetail = turtle.getItemDetail(dedicatedSlot)
164 if newDetail then
165 space = 64 - newDetail.count
166 else
167 space = 64
168 end
169 else
170 print("Dedicated slot for " .. seedType .. " is full; dropping extra seeds from slot " .. slot)
171 turtle.drop() -- Drop excess seeds.
172 end
173 end
174 end
175 end
176 turtle.select(dedicatedSlot)
177end
178
179--------------------------------------------------
180-- ATTEMPT TO PLANT A SPECIFIC CROP
181--------------------------------------------------
182local function attemptToPlant(cropBlock)
183 -- Map the crop block to the seed item and dedicated slot.
184 local seedType, dedicatedSlot
185 if cropBlock == "minecraft:wheat" then
186 seedType = "minecraft:wheat_seeds"
187 dedicatedSlot = 1
188 elseif cropBlock == "minecraft:carrots" then
189 seedType = "minecraft:carrot"
190 dedicatedSlot = 2
191 elseif cropBlock == "minecraft:potatoes" then
192 seedType = "minecraft:potato"
193 dedicatedSlot = 3
194 elseif cropBlock == "minecraft:beetroots" then
195 seedType = "minecraft:beetroot_seeds"
196 dedicatedSlot = 4
197 else
198 -- Default to wheat if unknown.
199 seedType = "minecraft:wheat_seeds"
200 dedicatedSlot = 1
201 end
202
203 -- Check the dedicated slot.
204 turtle.select(dedicatedSlot)
205 local slotItem = turtle.getItemDetail(dedicatedSlot)
206 if slotItem and slotItem.name ~= seedType then
207 -- The dedicated slot contains the wrong item; try to move it.
208 local emptySlot = nil
209 for s = 1, 16 do
210 if s ~= dedicatedSlot and not turtle.getItemDetail(s) then
211 emptySlot = s
212 break
213 end
214 end
215 if emptySlot then
216 turtle.transferTo(emptySlot)
217 else
218 turtle.drop()
219 end
220 end
221
222 -- If the slot is empty or wrong, search the inventory for the correct seed.
223 slotItem = turtle.getItemDetail(dedicatedSlot)
224 if not slotItem or slotItem.name ~= seedType then
225 local found = false
226 for s = 1, 16 do
227 if s ~= dedicatedSlot then
228 local detail = turtle.getItemDetail(s)
229 if detail and detail.name == seedType then
230 turtle.select(s)
231 turtle.transferTo(dedicatedSlot)
232 found = true
233 break
234 end
235 end
236 end
237 if not found then
238 return false
239 end
240 end
241
242 -- Attempt to plant.
243 turtle.select(dedicatedSlot)
244 local finalItem = turtle.getItemDetail(dedicatedSlot)
245 if finalItem and finalItem.name == seedType and finalItem.count > 0 then
246 turtle.placeDown()
247 return true
248 else
249 return false
250 end
251end
252
253--------------------------------------------------
254-- PLANT SEED WITH FALLBACK
255--------------------------------------------------
256local function plantSeedWithFallback(requestedBlock)
257 -- Try the requested crop first.
258 if attemptToPlant(requestedBlock) then
259 return
260 end
261
262 local fallbackOrder = { "minecraft:wheat", "minecraft:carrots", "minecraft:potatoes", "minecraft:beetroots" }
263 for _, fallbackBlock in ipairs(fallbackOrder) do
264 if fallbackBlock ~= requestedBlock then
265 if attemptToPlant(fallbackBlock) then
266 print("Planted fallback crop: " .. fallbackBlock)
267 return
268 end
269 end
270 end
271
272 print("No viable seeds found; skipping planting.")
273end
274
275--------------------------------------------------
276-- HELPER: CHECK IF CROP IS MATURE
277--------------------------------------------------
278local function isCropMature(blockName, age)
279 -- Maturity levels:
280 -- wheat: 7, carrots: 8, potatoes: 8, beetroots: 3
281 if blockName == "minecraft:wheat" then
282 return age == 7
283 elseif blockName == "minecraft:carrots" then
284 return age == 7
285 elseif blockName == "minecraft:potatoes" then
286 return age == 7
287 elseif blockName == "minecraft:beetroots" then
288 return age == 3
289 end
290 return false
291end
292
293--------------------------------------------------
294-- PLANT GROWTH CHECK ROUTINE
295--------------------------------------------------
296local function checkPlantGrowth()
297 -- Check two adjacent tiles.
298 while true do
299 turtle.turnLeft()
300 local success1, data1 = turtle.inspect()
301 local firstOk = true
302 if success1 then
303 if data1.name == "minecraft:wheat" or data1.name == "minecraft:carrots" or data1.name == "minecraft:potatoes" or data1.name == "minecraft:beetroots" then
304 if not isCropMature(data1.name, data1.state.age) then
305 firstOk = false
306 end
307 end
308 end
309
310 if not firstOk then
311 print("First adjacent crop not fully grown; waiting 5 minutes.")
312 turtle.turnRight() -- Revert orientation.
313 sleep(300)
314 else
315 turtle.turnLeft()
316 local success2, data2 = turtle.inspect()
317 local secondOk = true
318 if success2 then
319 if data2.name == "minecraft:wheat" or data2.name == "minecraft:carrots" or data2.name == "minecraft:potatoes" or data2.name == "minecraft:beetroots" then
320 if not isCropMature(data2.name, data2.state.age) then
321 secondOk = false
322 end
323 end
324 end
325
326 if not secondOk then
327 print("Second adjacent crop not fully grown; waiting 5 minutes.")
328 turtle.turnRight()
329 turtle.turnRight() -- Revert to original orientation.
330 sleep(300)
331 else
332 turtle.turnRight() -- Return to original orientation.
333 turtle.turnRight()
334 break
335 end
336 end
337 end
338end
339
340--------------------------------------------------
341-- MAIN FARMING PROCESS
342--------------------------------------------------
343local function mainFarmingProcess()
344 print("Starting main farming process.")
345 turtle.up()
346 turtle.turnLeft()
347 turtle.forward()
348
349 local row = 1
350 local lastPlantedCrop = nil
351 while true do
352 print("Processing row " .. row)
353 while true do
354 local successDown, dataDown = turtle.inspectDown()
355 if successDown then
356 if dataDown.name == "minecraft:torch" then
357 elseif dataDown.name == "minecraft:wheat" or dataDown.name == "minecraft:carrots" or dataDown.name == "minecraft:potatoes" or dataDown.name == "minecraft:beetroots" then
358 if isCropMature(dataDown.name, dataDown.state.age) then
359 if isInventoryFull() then
360 if dataDown.name == "minecraft:wheat" or dataDown.name == "minecraft:beetroots" then
361 organizeSeeds(dataDown.name)
362 end
363 end
364 turtle.digDown() -- Harvest the mature crop.
365 lastPlantedCrop = dataDown.name
366 plantSeedWithFallback(dataDown.name)
367 else
368 end
369 else
370 end
371 else
372 if lastPlantedCrop then
373 plantSeedWithFallback(lastPlantedCrop)
374 else
375 plantSeedWithFallback("minecraft:wheat")
376 end
377 end
378
379 local successFront, dataFront = turtle.inspect()
380 if successFront and (dataFront.name == "minecraft:glass" or dataFront.name == "minecraft:glass_pane") then
381 break -- End of current row.
382 end
383 turtle.forward()
384 end
385
386 if row % 2 == 1 then
387 turtle.turnLeft()
388 local successCheck, dataCheck = turtle.inspect()
389 if successCheck and (dataCheck.name == "minecraft:glass" or dataCheck.name == "minecraft:glass_pane") then
390 break
391 else
392 turtle.forward()
393 turtle.turnLeft()
394 end
395 else
396 turtle.turnRight()
397 local successCheck, dataCheck = turtle.inspect()
398 if successCheck and (dataCheck.name == "minecraft:glass" or dataCheck.name == "minecraft:glass_pane") then
399 break
400 else
401 turtle.forward()
402 turtle.turnRight()
403 end
404 end
405
406 row = row + 1
407 end
408
409 print("Main farming process complete.")
410end
411
412--------------------------------------------------
413-- MAIN LOOP
414--------------------------------------------------
415while true do
416 print("Thank you for using Beni's Farm Script!")
417 positionTurtle()
418 fuelCheck()
419 depositOperations()
420 checkPlantGrowth()
421 mainFarmingProcess()
422 print("Thank you for using Beni's Farm Script!")
423 print("Cycle complete; repositioning...")
424 positionTurtle()
425end
426