This tutorial is offered as part of the Ask A Pro Renewal Project (and How You Can Help!) tutorial series.
What this Tutorial Covers:
- How to setup your very own ComputerCraft Redstone Test Lab
- An introduction to the Redstone API
- How to detect a redstone input signal using redstone.getInput
- How to turn a redstone output on or off using redstone.setOutput
- How to tell if a redstone output is on using redstone.getOutput
- Program – Wait for Input
- Program – Blinky Lights
The following pre-requisites are essential in learning how to get around in ComputerCraft. If you don't read them before attempting this tutorial, you may find yourself struggling in the mechanics of using CraftOS.
- Computer Basics 1 by Lyqyd which covers how to create a computer, how to use the command line and the lua prompt, how to create a startup file, and how to use the cd and list commands.
- Computer Basics 2 by Lyqyd which covers the help, programs, label, id, copy, move, rename, mkdir commands.
Optional Tutorials
- Lua Basics -- Variable Scope, Code Blocks and Control Structures on understanding foundational Lua programming topics.
- Event Basics by Engineer for a good tutorial on using events.
- Redstone Tutorial by Engineer which gets a little bit into bundled cables as well.
Sources and Credits
- orginalbit for editing ideas.
- Lyqyd for editing ideas and assistance.
API Functions Used:
- redstone.getIntput() (also known as rs.getInput())
- redstone.getOutput() (also known as rs.getOutput())
- redstone.setOutput() (also known as rs.setOutput())
- os.pullEvent()
- os.sleep()
It is very useful to have a simple environment to test your ComputerCraft redstone ideas. The one described in this tutorial will work for all sorts of ComputerCraft redstone projects to test the functionality of your program as you design.
Materials Required
- 1 ComputerCraft Computer (normal or Advanced)
- 1 Block of Sandstone
- 1 Button
- 1 Lever
- 1 Redstone Lamp
- 4 Redstone Dust
Setup Diagram
Looking at the setup diagram from left to right, place the following:
- Redstone Lamp
- Skip a tile
- Computer
- Skip a tile
- Sandstone Block
- Skip a tile
- Lever
That's it. Check the diagram to make sure yours looks the same. At this point, you should have the Button and the Lever connecting to the Redstone Dust out of the right side of the Computer, and the Redstone Lamp connecting to the Redstone Dust out of the left side of the Computer. If you press the Button or toggle the Lever, the Redstone Dust to the right of the Computer will light up, however, the Redstone Lamp will stay unlit. This is what we want. We are going to control the Redstone Lamp from the Computer.
Using the Redstone API to Test Your Setup
First things first, what is an API, and more specifically, what is the Redstone API? An API is an acronym which stands for Application Programming Interface. It is a commonly used term in computer programming and web design which describes a way to programmatically interact with devices or web services. Google has an API to allow searches from a website you might design. The Weather Channel has an API to allow mobile phones and web pages to display weather information customized to their sites. Graphics cards have APIs to make displaying graphics easier for programmers. And ComputerCraft has APIs to allow you to interact with the virtual devices and objects in Minecraft. One of the ComputerCraft APIs is named "the Redstone API." You might have guessed already, but if you haven't, the Redstone API allows ComputerCraft Computers to interact with Redstone signals from within programs. With the Restone API, we can test wether Redstone Signals are on or off, detect whether there have been changes to Redstone signals, and even turn Redstone signals on or off like a Lever would do – all from within our programs.
We will test the setup using three Redstone Experiments and then we will write two exciting Redstone Programs.
Our First Redstone Lab Experiment – getInput
To start our first test, open the Computer and get into the interactive lua prompt (covered in Computer Basics 1 by Lyqyd). Type in rs.getInput("right") and press the return key. If your lever was off, your screen should look just like this:
Interactive Lua prompt.
Call exit() to exit.
lua>rs.getInput("right")
false
lua>
If you got an error, are you in the lua interactive mode? If you aren't type lua and press return. If you were, just retype the command until you get it right.
So what did we do? We used the Redstone API function getInput to test the input on the "right" side of the computer. The function returned false, meaning that the right side of the computer has no active redstone input (if it returned true – is your Lever on?).
Now turn the Lever on (make sure the redstone dust glows), and try it again. What happened? Did you get a return value of true? You should have.
A Closer Look at the Redstone API getInput Function
At this point, you might have a few questions, one of which might be "why do we type rs. before the getInput function?" That's a fair question, because we have been talking about the Redstone API, not the "rs" API. Programmers are always looking for shortcuts, and the folks at ComputerCraft knew that we would be using a lot of redstone functions in our whacky Minecraft creations. So, they gave programmers the ability to type either redstone or just rs when calling any of the functions in the Redstone API. The period (".") tells Lua that it is to call the function getInput in the redstone (or rs) namespace, much like calling library functions in other programming languages.
You might also wonder why we had to enclose the side we are testing in quotes. The rs.getInput function requires that we tell it what side we want the function to test. A ComputerCraft Computer is a block with six sides – top, bottom, front, back, left and right. Rather than trying to numerically represent the sides, the Redstone API lets us refer to the sides by their string representation. In Lua, raw strings are passed to functions by enclosing the string contents in quotes.
Finally, you probably have already guessed that the rs.getInput(<side as a string>) function returns a boolean value which represents the state of the redstone input on the side which was tested. From our experiment, if the redstone signal is on, the function returns true. Inversely, if the redstone signal is off, the function returns false.
Now that we know how to test the redstone input of a given side of the computer, let's figure out how to turn a redstone signal on or off.
Our Second Redstone Lab Experiment – setOutput
We have a Redstone Lamp connected to the left side of our Computer by a single tile of redstone dust. What good is a lamp if you can't turn it on or off? We can use the Computer to behave just like the Lever by calling the rs.setOutput function from the Redstone API (remember, it could also be referred to as the redstone.setOutput function). Can you figure out what you would need to type?
Try typing in rs.setOutput("left",true) and pressing the return key. What happened? Did the lamp turn on? If it did not, check your typing and try again. If it still didn't work, check and make sure you have redstone dust on the tile between the computer and the Redstone Lamp and try one more time. It should work.
Now try and turn it off. Type in rs.setOutput("left",false) and press the return key. It should go off.
What you might notice is that the setOutput function is very similar to the getInput function, with one small difference. Instead of the Redstone API telling us the state of an input on a side of the computer, we need to tell it the state that we want the output to be for a specific side. That's why the function takes two arguments but returns nothing. Practice turning the lamp on and off a few times on your own.
Our Third Redstone Lab Experiment – getOutput
We now can check the state of a redstone input on a given side, and we can set the redstone output on or off for a given side. But how can we tell whether the output on a side is already on or off? That's exactly what the rs.getOutput function is designed to do. When you are programming your creations, there may be times when you need to know if you a piston is already powered or not powered. In this manner you can decide to toggle the state of a redstone signal, turning what was on to off and vice-versa.
Check the state of the output on left side of the Computer. If it is on, turn it off and then test it again. If it is already off, turn it on and test it again. If you need help, expand the solution to see the commands you need to type in to accomplish this experiment. The solution example finds that the left side output is on, turns it off and then tests again.
Solution
lua>rs.getOutput("left")
true
lua>rs.setOutput("left",false)
lua>rs.getOutput("left")
false
You now know how to check the input of a redstone signal on a given side of a computer using rs.getInput, turn a redstone output on or off on a given side of a computer using rs.setOutput, and check to see if a redstone output is on or off on a given side of a computer using rs.getOutput. You are ready to make your first Redstone Program!!!
Program – Wait for Input
We want a program that will wait for the redstone input to change, and then turn on or off the redstone signal when it does change. In practical terms, what we want is to turn the Redstone Lamp on when the Lever is on or when the Button is pressed, and turn the Redstone Lamp off when the Lever is turned off or the Button resets.
To do this, we need some function that will wait for a redstone input to change. We will use the os.pullEvent("redstone") function to accomplish that for us. The os.pullEvent function waits for all sorts of events that can occur in ComputerCraft – key presses, monitor touches, modem messages and what we are interested in – redstone signals. There are other tutorials covering the event system in ComputerCraft, so we will just use the function for our program with the understanding that the os.pullEvent("redstone") function will only respond to redstone input events that occur on any side of our Computer. Until the function detects an event, the program will sit by in idle and wait.
What do we know? We have input signals that we want to monitor on the right side of the computer. We have an output signal that we want to control on the left side of the computer. We want the program to startup and turn the redstone lamp off if the input is already off, or turn it on if the input is already on. When we detect changes to the input signal on the right side of the computer, we want to do something to the output on the left side of the computer. We want to keep doing that until we terminate the program or shut down the computer.
The first thing we need to do is get out of the interactive lua mode using the exit() command or restart your ComputerCraft computer. We are going to call this program wait. So, type edit wait and press the return key. You should be in the program editor now.
Type in the following code:
if rs.getInput("right") then
rs.setOutput("left",true)
else
rs.setOutput("left",false)
end
while (true) do
os.pullEvent("redstone")
if rs.getInput("right") then
rs.setOutput("left",true)
else
rs.setOutput("left",false)
end
end
Save the program and exit the editor. Assuming you named the program wait, type in wait and press the return key. The program should run. If you need to edit mistakes, just type edit wait and press return to edit your code again.
How does this program work? Well, the first thing we wanted to achieve was to synchronize the state of the right side output with the left side input, that is if the lever or button were sending a redstone signal, we wanted to make sure the Redstone Lamp was on, or if the lever or button were not sending a redstone signal, we wanted the light to be off. That is exactly what the first few lines of the program do:
if rs.getInput("right") then
rs.setOutput("left",true)
else
rs.setOutput("left",false)
end
When examining the if condition, keep in mind that rs.getInput will return a boolean true or false, making it unnecessary to use an equality comparator. When rs.getInput returns its boolean result, the if statement will resolve to if (return value from rs.Input)then… So if the return value is true (meaning the input was on), the if condition will be satisfied. When the return value is false (the input is off), the else condition will be satisfied.
Next, once synchronized, we want our program to run forever or die when we kill it. That is the purpose of this while (true) loop: it will run forever because the condition is always true.
while (true) do
… keep turning the lamp on and off ...
end
Additionally, we want to pause the program until there are changes to the redstone input state of the right side. That is where the pullEvent function comes in handy. Finally, when the redstone input state on the right side changes, we want to set the output side to the same state as the input side. We already did that at the beginning, so we just repeat it here in the while loop.
if rs.getInput("right") then
rs.setOutput("left",true)
else
rs.setOutput("left",false)
end
So now our program starts up and turns the Redstone Lamp on or off depending on whether the Lever or Button state is on or off. Then it waits for any changes to the lever or button state and changes the Redstone Lamp accordingly. Rinse and repeat.
Can we do better? What happens if we decide to use different sides for input or output? That would take a whole bunch of editing to change the program to the new sides. A better practice would be to plan ahead for such eventualities. Can we simplify the testing that we do in the program? Since we know that we want the input and output sides to have the same redstone state, we can optimize the code a little by combining the setOutput and getInput functions. Edit the program to be like this instead (you could remove (rm) the old program and just recreate it):
local inputSide = "right"
local outputSide = "left"
rs.setOutput(outputSide,rs.getInput(inputSide))
while (true) do
os.pullEvent("redstone")
rs.setOutput(outputSide,rs.getInput(inputSide))
end
After correcting errors in syntax, the program should behave exactly the way the previous program worked – albeit more efficiently and much more elegantly.
Look closely at the code that we used to get rid of the if … else control structure. We already know that the getInput function returns a boolean true or false. We also know that the setOutput is looking for a boolean as its second argument. So, we allow the getInput function to supply the second argument to the setOutput function and get rid of the need for the if … else control structure.
Program – Blinky Lights
Our final program in this tutorial is a blinky light program. What we want to accomplish is to flash the Redstone Lamp any time the right input has a Redstone Signal. Flashing requires some sort of timer function, and we are going to use another os function called sleep to get the job done. Essentially, os.sleep allows us to specify an amount of time for the program to sleep before resuming. That will let us turn the Redstone Lamp on for a period of time and then turn the Redstone Lamp off for a period of time … in other words, a blinky light.
The Button will turn a redstone signal on for one second and then turn off, so if we want it to flash more than once during the period the Button's redstone signal is active, we need to set our values for the intervals to much less than one second. We will try a value of 0.3 seconds for the on duration, and 0.3 seconds for the off duration and see how that looks. Ideally, what we want is for flashing to continue for as long as the signal is present. We might need to play around with the on/off duration to find the optimal "blinkyness" (a highly technical term invented just for this tutorial) for our Redstone Lamp. So, we will use some of the optimization lessons learned from the last program to make our life easier here. Like before, enter the editor with edit <program name>. For this tutorial, type in edit blinky and press enter.
Here is the code for blinky. As you type in the code, notice that we give variables names which make sense when you consider their purpose, and this helps make the code much more readable. For example, we will name the variable that holds the value of which side we want to test for input as inputSide. The variable onInterval has to do with – you guessed it – how long we want the Redstone Lamp to stay on before we turn it off again. This practice of giving variables common-sense names rather than "a" or "zaphod" is sometimes referred to as self-documenting code, and it is a useful habit to adopt as you program in ComputerCraft. You may also notice that we have given code lines which belong to the same code block the same level of indentation – another useful habit which makes reading code much easier.
local inputSide = "right"
local outputSide = "left"
local onInterval = 0.3
local offInterval = 0.3
rs.setOutput(outputSide,false)
while (true) do
os.pullEvent("redstone")
while(rs.getInput(inputSide))
rs.setOutput(outputSide,true)
os.sleep(onInterval)
rs.setOutput(outputSide,false)
os.sleep(offInterval)
end
end
When you are finished editing, exit the editor after saving the program and then run it.
The program starts by making sure the Redstone Lamp is off, regardless of the state of the inputs. What this means is that if the lever was on at program startup, you will have to toggle the lever to trigger a new redstone event for the os.pullEvent to read before you notice any change in the Redstone Lamp. You can play around with the onInterval variable and the offInterval variable to see what effects you can achieve in the "blinkyness" factor (you may find that 0.3 seconds for both intervals is quite pleasing, or you may not). When the pullEvent detects a redstone event, a new while loop is started which will continue until the getInput for the inputSide becomes false. You may recall from prior tutorials that if the while condition is already false when the loop begins, none of the statements in the code block will execute. However, assuming the loop does execute, the outputSide will be turned on, the program will pause for the duration of the onInterval, and then the outputSide will be turned off followed by another os.sleep – this time for the duration of the offInterval. This process will continue until the redstone state of the inputSide becomes false. Finally, the program will wait for another redstone event and repeat the process all over again.
Wrapping Up
In this tutorial, you learned how to use ComputerCraft's Redstone API to detect a redstone input signal using rs.getInput. You also explored using the Redstone API's rs.setOutput to turn on and off redstone outputs. In addition to being able to detect input signals, you learned that you can use the rs.getOutput function to check the state of a redstone output signal.
We created two programs, one which turns on and off a Redstone Lamp based on the state of a redstone input and the judicious use of the os.PullEvent("redstone") function. This program can be extended to any number of devices much more complex than a Redstone Lamp (consider controlling pistons for example). We also learned a few tricks on optimizing code by combining the return value of a function to supply an argument of another function. Finally, we coded the exciting and highly necessary Blinky Lights program, which for all of its glitz and glamor seems silly and impractical on first blush (although it did give us some experience with the useful os.sleep() function from the os API). However, because you are on your way to becoming a creative ComputerCraft programmer, we can rapidly expect that you will find myriad ways to turn the Blinky Lights program into something amazing – perhaps into a control system for an arrow dispenser of doom which unleashes a reservoir of lava onto unsuspecting villagers in a small backwoods community frequented by roaming bands of creepers and wannabe My Little Ponies …
Happy ComputerCrafting.