Jump to content
  • Sky
  • Blueberry
  • Slate
  • Blackcurrant
  • Watermelon
  • Strawberry
  • Orange
  • Banana
  • Apple
  • Emerald
  • Chocolate
  • Charcoal
  • 0
XenizedKitsune

Sky Factory 3 Tree Farm Robot

Question

In my Sky Factory 3 world, I would like to fully automate a farm for the Pam's Harvestcraft crops and trees. The problem became how to automate harvesting the nuts/fruits (since EnderIO and similar mods just break the trees). I didn't want to line an orchard with mechanical users, so I turned to OpenComputers after noticing I can program a robot to do it for me.

I've spent the past few days trying to learn how to build/program a robot, and finally managed to harvest vanilla at all (by jamming a bunch of move and use commands in one .lua ). The next step was suppose to make it react to a redstone signal (starting its harvest routine when a chest of bonemeal is full, thank you Storage Drawers).

However, I can NOT for the life of me figure out how to make a robot react to a redstone signal AT ALL. Even something as simple as printing "true" when it gets one. All the tutorials/help I can find are either 1) Saying what a redstone card is at all, not how to use it,  2) Incomplete snippits of code for a computer system, (which gives me lots of errors when I try to add them into my robot. Could be my incompetence, but that's beside the point) or 3) for ComputerCraft. I only just picked up OpenComputers and Lua 2 days ago, I don't know how to translate ComputerCraft code into OpenComputers code.

 

Any help figuring out how redstone cards work in robots would be greatly appreciated. (And of course any tips on how to make a robot sleep/wait until it gets a redstone signal, then spring into action, would fantastic.)

Link to post
Share on other sites

8 answers to this question

Recommended Posts

  • 1
  • Solution

When a redstone input changes, the "redstone_changed" event is fired. It contains the redstone card address, the side, the previous input strength, and the current strength.

To wait for an event, use event.pull. You need to require("event") before you use any of the event library's functions.

Here's an example.

local event = require("event")
local sides = require("sides")

while true do
  local e, addr, side, prev, current = event.pull("redstone_changed")
  if e and side == sides.back and prev == 0 then
    -- your code here
    collectFruits()
  end
end

 

Link to post
Share on other sites
  • 1

Yes, functions are real... I'm not really sure what you meant by that.. But here's an example anyways..

-- # A named function
local function sum( a, b )
	return a + b
end

-- # An 'anonymous' function stored in the named variable 'mul'
local mul = function( a, b )
	return a * b
end

local pow -- # forward declaration allows us to reference the caller 'pow' inside of itself.
pow = function( a, p )
	if not p then -- # return a partial application
		return function( p2 )
			-- # remember the initial number 'a' and take a power of p2 to apply
			return pow( a, p2 )
		end
	end

	return a^p
end
--[[ #
	local val = pow( 3, 2 ) --> // 9
	local f = pow( 3 ) --> // function( p2 ) return 3^p2 end
	local val2 = f( 2 ) --> // 9
]]

 

Link to post
Share on other sites
  • 1
2 hours ago, XenizedKitsune said:

(Plus running between two different trees means putting in 'robot.forward()' half a dozen times and that feels so crude...)

What you're looking for is a function. Specifically a 'for' or while loop in a function. Here is a crude one of the former that 'could' be made way better (features n stuff)...

local robot = require 'robot'

local function forward( times )
	times = times or 1
	
	local success, reason, moves = false, nil, 0
	for move = 1, times do
		success, reason = robot.forward()
		if not success then break end 
		moves = moves + 1
	end

	return success, moves, reason
end

-- # USAGE
-- # Let's say we're moving 3 forward, on a clear path.
forward( 3 ) -- # // true, 3, nil (success, moves, reasonForFailure)

-- # Now we try another 3 with and obstruction 2 blocks ahead of the robot.
forward( 3 ) -- # // false, 1, "path obstructed... or something like this that component.robot.move(side) returns when it fails"

 

Link to post
Share on other sites
  • 1

Ah, right. When robot returns to the start, it receives the redstone_changed event and immediately repeats the code. The fix is to consume this event before pulling -- this can be done with os.sleep().

while true do
  local e, addr, side, prev, current = event.pull("redstone_changed")
  if e and side == sides.back and prev == 0 then
    farmTrees()
  end
  os.sleep(0.25)
end

 

Link to post
Share on other sites
  • 0

SUCCESS! The robot has harvested a vanilla bean when I pushed a button! Thank you so much, Finger!

 

The next step now is to teach the robot to equip bonemeal, though that SHOULD be relatively easy... Possibly something like

local bonemeal = require("component")

bonemeal.inventory_controller.equip

Or maybe I need to require just "component"? Trial and error may help.

Just needed to require "component". Trying to have it require "inventory_controller" as well gave me... quite the long error message as it looked through every single folder in the 'bot.

 

And as a final note, do functions work in OpenComputers? I can see they're a thing in real Lua, but I've yet to see any mention of functions in OpenComputers tutorials... They could help me clean up my code some.

Edited by XenizedKitsune
Learned the real code myself
Link to post
Share on other sites
  • 0
1 hour ago, Molinko said:

I'm not really sure what you meant by that...

I was simply wondering how functions worked in OpenComputers. It would have been cool if I could crunch my harvest routine into a function so I don't have to hit tab twice after every single line.

Due to the random nature of the fruit spawns on each tree, there's nothing repetitive in my code, so functions aren't totally necessary. Thank you for the example, though.

 

Okay, I'm ALMOST done with the code, but there is one last issue that may save me a few dozen lines. How can you make a robot move more than one block in a single line?

It won't stop in a block occupied by a fruit, but players can pass directly through them. Theoretically, so can robots, if its destination is beyond the fruit... I hope?

(Plus running between two different trees means putting in 'robot.forward()' half a dozen times and that feels so crude...)

Link to post
Share on other sites
  • 0

Once again, Molinko, you're a lifesaver. The function works beautifully. I don't need it to be elegant or more condensed/complicated if it works exactly as intended, so you did wonderfully.

 

As with all coding, the moment you think you have it all down perfectly, another bug shows up. This time, I think I'm just missing some kind of break.

Right now, as soon as the robot gets a redstone signal, it'll run its farming operation. Which is fine, until it completes the operation. Instead of waiting for another redstone signal, it repeats the operation again, ignoring the signal or lack thereof.

I ran a separate test trying out a "do return end" line, but that ended the program entirely, which I don't want. (A farm isn't helpful if it turns off until I manually restart it every time).

Where would I need a break/return to get it back to looking for that signal, and how would it be coded?

For reference, here's the code I have thus far, minus the manual pathing I put in to navigate the farm.

local robot = require("robot")
local sides = require("sides")
local event = require("event")
local component = require("component")
local function forward(times)
  times = times or 1
  local success, reason, moves = false, nil, 0
  for move = 1, times do
    success, reason = robot.forward()
    if not success then break end
    moves = moves + 1
  end
end

while true do
  local e, addr, side, prev, current = event.pull("redstone_changed")
  if e and side == sides.back and prev == 0 then
    robot.farmTrees -- # Here's where I've got a ton of manual guidance. Thanks for the random spawns, Pam
    -- # Right here is where I would think a break or return goes.
  end
end

Looking back, it may help to use the redstone card component to look for a signal after it's done farming... if it doesn't get any, then break the sequence. And if there is a signal, my tree farm is ready to be harvested anyway, so it'll get back to work.

A simple test where the robot bounces up and down whenever it reads a signal of 1 (after Super Circuit Maker subtracts 14 from a lever's signal)  confirmed that I can make it work whenever it gets a signal. The robot stopped bouncing when I flipped the lever off, dropping the signal to 0.

After I get some sleep tonight, I'll try replacing the event.pull("redstone_changed") group with the code I came up with and see if I break anything.

I'll leave the code for my redstone test here in case anyone from outside my timezone can help an amateur like myself out.

local component = require("component")
local sides = require("sides")
local robot = require("robot")

while true do
  if component.redstone.getInput(sides.back) == 1 then
    robot.up()
    robot.down()
  end
end
-- # Lever on, robot bounces like a ball. Lever off, robot stops on the floor.
-- # Though for some reason Ctrl+Alt+C won't kill the command, so I have to shut down the bot to stop the .lua from running.

I'll look into how the redstone card works again, but I would appreciate any help figuring out how to break out of the loop without shutting the program down entirely.

Edited by XenizedKitsune
Making progress with the redstone card
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.