iovoid 0 Posted November 29, 2023 Share Posted November 29, 2023 Once I wanted to automatically farm using OpenComputers. First I made robot, but 1.7.10's block update stutter made active robot annihilate framerate. Thus I opted for entity-based agent and made code to operate drone for autonomous farming. And now I decided to release the code for everyone to enjoy my work. Feel free to improve upon it, or use as is. Example setup: Inventory of active drone: Drone minimum components: Drone Case (Tier 1) Geolyzer Inventory Upgrade Central Processing Unit (CPU) (Tier 1) Memory (Tier 1) EEPROM with code provided How to setup: Drone never changes altitude and operates on single square area that may not be permanently obstructed. You must till farm plot manually. Drones always use global axes for movement, there's no rotation to keep track of. Adjust localX and localZ variables at start of code to designate dock area, drone must always boot up at dock, on top of charger with my example setup. If drone starts beeping upon bootup, you messed up the setup, drone is unable to locate inventory (or it's full). Drone also will start beeping at dock if output is full, just collect your obscene amount of produce when that occurs. minX/minZ/maxX/maxZ similarly define corners of farm plot. On my example setup screenshot player is facing north-west (towards negative X and negative Z), dock is at (15, 15), while most remote corner of farm plot is (0, 0). no_farm table contains exceptions where no farming operation should ever occur, using same local coordinate system. keep_seeds should allow for few missing plants to be replanted (but drone won't be able to deal with trampled fields automatically due to inability to use tools), you might want higher value if plant you are working with has chance to not drop seeds. ensure_space should be set to maximum amount of item types mature plant yields on breaking (2 being value for wheat or potatoes), otherwise you will suffer minor item loss if drone overflows. If two outputs are common (wheat), either use value of 1 or add another inventory upgrade. As I understand Minecraft farming mechanics, monoculture farming would not be faster than farming two plant types at once with plants being in lines. plant() contains logic for seed slot selection, adjust if you want to farm more than two types at single plot, but beware inventory constraints of drone and multiple outputs. Code, goes into EEPROM of drone: local d = component.proxy(component.list("drone", true)()) local g = component.proxy(component.list("geolyzer", true)()) local c = computer d.setLightColor(0xff00ff) local no_farm = { [15] = { [15] = true, }, [12] = { [3] = true, [12] = true, }, [3] = { [3] = true, [12] = true, }, } local to_collect = { ["minecraft:potatoes"] = true, ["minecraft:carrots"] = true, } local seed_slot = { [1] = true, [2] = true, } local keep_seeds = 4 local ensure_space = 2 local localX = 15 local localZ = 15 local minX = 0 local minZ = 0 local maxX = 15 local maxZ = 15 local inv_side = 1 local inv_name = "minecraft:chest" local startX = localX local startZ = localZ local function sleep(sec) local dl = c.uptime() + sec repeat c.pullSignal(dl - computer.uptime()) until c.uptime() >= dl end local function attn() c.beep(1500, 0.2) c.beep(1700, 0.2) c.beep(1300, 0.2) sleep(3) end local function plant() local slot = localX % 2 + 1 if d.count(slot) > 1 then d.select(slot) if not d.place(0) then attn() end else attn() end end local first_free local function got_free_slots(wanted, no_heur) local found = 0 for slot = first_free or 1, d.inventorySize() do if d.count(slot) == 0 then found = found + 1 first_free = first_free or slot end if found >= wanted then return true end end if first_free and not no_heur then first_free = nil return got_free_slots(wanted, true) end return false end local function farm() local found, desc = d.detect(0) if not found and desc == "air" then plant() elseif found and desc == "passable" then local block = g.analyze(0) if block ~= nil and block.growth ~= nil then if block.growth == 1 and to_collect[block.name] then d.select(1) d.swing(0) plant() end else attn() end else attn() end end local function put_away_excess() while true do local found, desc = d.detect(inv_side) if found and desc == "solid" then local block = g.analyze(inv_side) if block ~= nil and block.name == inv_name then break end end attn() end repeat local done = true for slot = 1, d.inventorySize() do local amt = d.count(slot) if amt > 0 then d.select(slot) local to_drop = math.huge if seed_slot[slot] then to_drop = amt - keep_seeds end if to_drop > 0 and not d.drop(inv_side, to_drop) then done = false attn() break end end end until done first_free = nil end local function vec_len(oX, oZ) return math.sqrt(oX*oX + oZ*oZ) end local function move_to(tgtX, tgtZ, precise) local offX = tgtX - localX local offZ = tgtZ - localZ if offX == 0 and offZ == 0 then return end d.move(offX, 0, offZ) local moved local goaldist = 0.45 local goalvel = 2 local timemult = 1 if precise then goaldist = 0.1 goalvel = 0.1 timemult = timemult * 2 end local dl = c.uptime() + vec_len(offX, offZ) * timemult repeat moved = d.getOffset() <= goaldist and d.getVelocity() <= goalvel if c.uptime() >= dl then break end until moved if moved then localX = localX + offX localZ = localZ + offZ else d.move(-offX, 0, -offZ) attn() end end local workX = startX local workZ = startZ local function next_spot() if workX < maxX then workX = workX + 1 else workX = minX if workZ < maxZ then workZ = workZ + 1 else workZ = minZ end end if no_farm[workX] ~= nil and no_farm[workX][workZ] then next_spot() end return workX, workZ end local function dock(optional) if optional and c.energy() >= 500 and got_free_slots(ensure_space) then return end move_to(startX, startZ, true) put_away_excess() while c.energy() < c.maxEnergy() - 500 do sleep(3) end end dock(false) while true do dock(true) move_to(next_spot()) farm() end License terms for my code: This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to <https://unlicense.org/> Ideas for improvement: More robust detection of drone actually being at new position without slowing down operation. I've been adjusting goaldist and goalvel until drone stopped failing farm(), with no strong theory for what should be ideal values; Change scanlines pattern into zig-zag pattern for minor increase in farming speed; Have companion robot craft away wheat and similar things into cubes and/or fix trampled field; Handling of plants not exposing "growth" to geolyzer, like Immersive Engineering's hemp; Handling of multi-tile plants, like said hemp; Rotating between many plant types with just few being planted at given time; Melon and pumpkin farming (will likely release drone for that soon, as I already got stutter-inducing robot doing this). Quote Link to post Share on other sites