This workshop uses the Node-RED framework as development tool for JavaScript. Building on functionality available for generic programming challenges, we’re going to use the communication standard TCP (Transmission Control Protocol) to interact with the Minecraft API (Application Programming Interface). The material is aimed at people who have had first experience with the Minecraft API on a Raspberry Pi (say, using Python), who now want to understand what's going on behind the scenes and what TCP, API and all those other acronyms mean. It also introduces flow-based programming concepts.
Andreas Schleicher presents at the launch of What does child empowerment mean...
Node-RED and Minecraft - CamJam September 2015
1. CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
- 1 -
http://nodered.org
An
introduction
to
flow-based
programming
using
Node-RED
! Node-RED
is
a
visual
tool
for
wiring
the
Internet
of
Things
(IoT).
Node-‐RED
is
platform-‐independent,
but
has
been
developed
with
small
computers
such
as
the
Raspberry
Pi
in
mind.
! Traditional
IoT
development
can
be
very
technical:
Access
to
the
GPIO
and
other
hardware
requires
skills
in
C
or
assembler,
output
of
data
to
web
services
or
sending
tweets
and
emails
requires
the
use
of
complex
APIs.
Node-RED
takes
care
of
the
technicalities
and
lets
you
concentrate
on
the
logic
of
your
workflow
! While
most
programming
in
Node-‐RED
is
done
visually
using
pre-‐defined
functions
(“nodes”),
any
additional
functionality
can
be
added
in
JavaScript.
! Node-RED
is
a
multi-purpose
survival
tool
–
use
it
for
any
prototyping!
WORKSHOP
CONTENT:
In
this
workshop,
we’re
going
to
use
Node-‐RED
as
a
development
tool
for
JavaScript.
Building
on
functionality
available
for
generic
programming
challenges,
we’re
going
to
use
the
communication
standard
TCP
(Transmission
Control
Protocol)
to
interact
with
the
Minecraft
API
(Application
Programming
Interface).
2. CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
- 2 -
Technical
background:
For
this
workshop,
you
will
find
a
Raspberry
Pi
with
Node-‐RED
already
installed.
While
the
installation
of
Node-‐RED
software
is
relatively
easy,
it
would
be
difficult
to
include
this
step
within
the
time
constraints
of
the
exercise.
On
a
fresh
and
up-‐to-‐date
Raspian
installation
we
added:
node.js,
npm
and
Node-‐RED
as
per:
http://nodered.org/docs/hardware/raspberrypi.html
Note:
On
your
own
system,
to
leverage
the
power
of
Node-‐RED,
consider
installing
the
node
for
GPIO
access
as
well.
1)
Exercise:
Starting
Node-RED
as
Raspberry
Pi
user
Node-‐RED
can
be
installed
as
a
service
on
the
Raspberry
Pi,
i.e.
as
a
program
that’s
always
executed
when
your
Pi
is
running.
However,
this
is
only
useful
if
you
want
to
commit
your
Pi
for
this
particular
use
as
it
can
consume
considerable
resources.
For
everyone
else,
it’s
recommended
to
start
Node-‐RED
only
when
needed:
1. Open
the
LXTerminal
to
see
a
console
that
allows
you
to
enter
Linux
commands.
2. Start
Node-‐RED
by
issuing
“node-red”.
You
should
now
see
Node-‐RED
starting
up
–
that
may
take
a
few
seconds:
Congratulations.
You’re
now
ready
for
the
exercises.
Node-‐RED
represents
a
server
on
the
basis
of
node.js
and
interacts
with
the
user
through
a
graphical
user
interface.
It
can
be
reached
on
port
1880.
To
use
Node-RED,
open
a
web
browser
and
direct
it
to
http://localhost:1880
It’s
useful
to
remember
that
Node-‐RED
acts
as
a
server
in
your
entire
network.
That
is,
if
your
Raspberry
Pi’s
internal
IP
address
is
something
like
192.x.x.x,
every
computer
in
your
network
can
open
the
Node-‐RED
GUI
through
http://192.x.x.x:1880.
You
can
make
your
system
more
restricted/secure
by
following
the
configuration
advice
on
http://nodered.org/docs/security.html.
2)
Exercise:
Your
first
flow
–
this
is
a
recap
for
those
who
attended
the
last
course(s)
The
best
way
to
explain
“a
flow”
is
by
creating
one.
In
this
mini
flow,
we’re
going
to
inject
a
value
into
our
debug
window
(refer
to
page
1
for
what
the
GUI
elements
are
called).
1. Open
the
Epiphany
Web
Browser.
(It
supports
JavaScript
better
than
Midori).
2. In
the
address
line,
enter
localhost:1880.
You
will
then
see
the
Node-‐RED
GUI.
3. CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
- 3 -
3. Drag
and
drop
an
“inject”
node
from
the
nodes
library
into
the
flow
editor
(once
you’ve
chosen
the
inject
node,
you
should
see
some
general
explanation
about
its
functionality
in
the
info
pane
–
no
need
to
read
that
now).
4. Drag
and
drop
a
“debug”
node
from
the
nodes
library
into
the
flow
editor.
5. Create
a
pipe
between
the
inject
and
debug
nodes
by
drawing
a
connection
between
their
small
grey
rounded
rectangles.
6. Change
from
the
info
pane
to
the
debug
pane
(upper
right).
7. Deploy
(=start)
your
flow.
8. Once
deployed,
press
the
left
blue
rectangle
that’s
attached
to
the
inject
node.
Check
what’s
happening
in
the
debug
pane.
(Yes,
that’s
a
Unix
time
stamp).
3)
Exercise:
Finding
the
Minecraft
API
and
understanding
the
protocol
1. Open
another
LXTerminal
and
change
to
your
Minecraft
installation
by
issuing
“cd
/opt/minecraft-pi”.
2. In
the
API
directory
(“cd
api”),
get
a
list
of
available
files
and
directories
(“ls”).
Those
with
previous
programming
experience
may
recognise
the
python
sub-‐directory.
Inside
you
would
find
the
files
that
expose
the
Minecraft
functionality
of
the
mcpi
package
to
Python.
It’s
important
to
note
that
the
Application
Programmers
Interface
(API)
–
be
it
for
a
locally
installed
application
like
Minecraft
or
a
web
server
that
listens
to
your
commands
over
the
Internet
–
is
just
a
convention
on
which
interface
(local
socket
or
IP
address,
port)
an
application
is
listening
to
other
programs
(like
yours),
which
commands
are
available
and
what
parameters
in
which
formats
are
expected.
The
mcpi
package
encapsulates
these
concepts
(connection,
commands)
in
easy-‐to-‐use
Python
commands.
Sometimes
the
underlying
specification
is
not
communicated
and
as
a
programmer
you’re
stuck
with
the
functions
available
in
the
higher-‐level
library.
However,
the
Minecraft
API
is
rather
transparent
and
if
you…
3. Change
into
the
spec
directory
(“cd
spec”),
you
are
going
to
find
mcpi_protocol_spec.txt
–
a
humble
text
file
with
the
information
that
you
require.
4. Open
the
file
in
an
editor
(“nano
mcpi_protocol_spec.txt”)
and
have
a
look
around.
Most
modern
web
services
(including
Twitter
or
the
BBC)
provide
APIs
for
programmatic
retrieval
of
information.
If
you’re
interested
how
to
use
APIs
over
the
Internet
in
Node-‐RED,
I’ve
put
up
a
guide
on
accessing
IoT
platforms
that
can
serve
as
an
entry
point:
http://www.slideshare.net/BorisAdryan/node-red-iotplatformtest
The
specification
states
that
the
Minecraft
binary
listens
to
incoming
messages
at
“TCP
port
4711”
and
expects
character
strings
that
are
terminated
with
a
“n”
(Unix
linefeed).
A
following
schematic
of
the
Open
Systems
Interconnection
(OSI)
Model
helps
to
digest
this:
In
a
nutshell,
once
a
physical
connection
is
established
between
two
devices
(Level
1)
and
they
can
exchange
signals
(Levels
2+3),
Level
4
in
the
OSI
Model
takes
care
of
housekeeping
jobs:
Is
there
an
error
in
the
communication?
Can
we
recover
from
small
errors?
Do
4. CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
- 4 -
information
packages
arrive
in
the
right
order?
While
some
protocols
like
UDP
optimise
for
high
throughput
(little
error
checking,
little
redundancy),
others
are
slower
but
more
secure
in
terms
of
data
integrity
(like
TCP).
http://programmerhelp404.blogspot.co.uk/2014/01/iso-osi-layer-model-tcpip-model.html
It’s
important
to
understand
that
these
communication
routes
exist
on
the
Internet,
but
at
the
same
time
localhost
(IP:
127.0.0.1)
offers
the
same
functionalities
on
your
local
computer.
One
can
imagine
the
communication
via
the
Internet
Protocol
(IP,
Level
3)
like
a
motorway,
but
there
are
65536
(216)
different
lanes,
commonly
referred
to
as
port.
4)
Exercise:
“Hello
World”
in
Minecraft,
Node-RED
style
Please
start
Minecraft
and
open
a
new
world.
You
may
want
to
arrange
the
console
windows,
the
browser
and
Minecraft
to
your
liking…
…yes,
there’s
always
too
little
space
on
that
screen
and
Model
1
Raspberry
Pis
are
not
the
fastest
machines
to
do
this.
In
Node-RED,
1. Double-‐click
your
input
node,
and
once
the
associated
dialog
opens,
change
the
Payload
to
type
string
and
write
“Hello
World”
in
the
empty
text
field
below.
5. CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
- 5 -
2. Drag-‐and-‐drop
in
a
function
node.
This
is
the
node
type
that
allows
you
to
directly
interact
with
Node-‐RED
messages
(by
default
having
a
‘payload’
and
a
‘topic’)
in
JavaScript.
3. In
your
function
node,
write
“msg.payload
=
"chat.post("+msg.payload+")n";”
before
return
msg;
This
line
is
going
to
take
the
incoming
msg.payload
(“Hello
World”),
and
assigns
new
content
“chat.post(Hello
World)n”
to
the
variable.
chat.post
is
a
command
we’ve
learned
from
the
mcpi_protocol_spec.txt,
and
Minecraft
is
going
to
assert
it
as
such
when
it’s
followed
by
a
line
break
(Unix
definition:
n).
4. Drag-‐and-‐drop
a
TCP
node
from
the
output
panel.
Set
it
up
with
the
following
parameters:
5. Connect
the
nodes
like
this:
6. Deploy.
Test
your
flow
by
triggering
the
inject
node.
Do
you
see
what
you
expected?
5)
Exercise:
Move
Steve
around
-
and
build
stuff
You’ve
been
there
before,
but
probably
in
Python.
Now
try
it
with
raw
ASCII
strings.
1. Have
a
look
around
the
protocol
specification
and
look
for
the
command
that
sets
the
player
to
a
new
coordinate.
2. Set
a
wooden
block
directly
in
front
of
you.
(Hint:
blockTypeID
for
wood
is
17;
and
hard-‐code
the
coordinate
for
now).
6. CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
- 6 -
6)
Exercise:
Retrieving
values
from
Minecraft
So
far
our
interaction
with
Minecraft
was
rather
one-‐directional.
We
just
sent
command
strings
that
had
an
effect
on
the
Minecraft
world.
Now
we’re
going
to
modify
our
flow
so
we
can
query
values
like
our
own
position
via
the
API.
The
overall
anatomy
of
our
flow
is
going
to
look
like
this:
1. Use
an
inject
node
(here
named
trigger)
to
start
the
flow.
2. In
the
appropriate
function
node,
set
“msg.payload
=
"player.getPos()n";”
3. Instead
of
a
TCP
out
node,
we’re
now
going
to
use
a
TCP
request
node
that
allows
for
bi-‐directional
communication.
Configure
the
node
like
this:
Just
as
we
indicated
the
end
of
our
message
to
the
server
with
a
“n”
character,
Minecraft
terminates
its
return
messages
with
the
same
character.
4. By
default
the
TCP
request
node
returns
a
buffer,
and
we
need
to
convert
the
information
from
Node-‐RED
using
“msg.payload
=
msg.payload.toString();”
in
a
function
node.
5. The
flow
concludes
with
a
debug
node.
If
you’re
having
trouble
with
the
flow,
consider
sending
output
to
debug
panel
and
console.
6. Deploy.
Have
a
walk
around
Minecraft
and
trigger
your
flow.
Do
you
see
what
you
expected?
7)
Exercise:
Event-driven
programming
and
loops
By
now
you
may
have
realised
that
our
Node-‐RED
flows
were
linear
series
of
commands.
Once
triggered,
we
sent
a
command,
retrieved
information
and
displayed
it.
But,
for
example,
how
can
we
iterate
over
a
set
of
coordinates
and
execute
world.getBlock(x,y,z)
for
Steve’s
immediate
neighbourhood?
7. CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
- 7 -
For
this,
we’re
going
to
extend
our
flow
a
little
bit.
First,
look
at
the
overall
anatomy
of
our
flow.
It’s
a
bit
of
a
mouth
full:
First,
we
translate
Steve’s
position
into
a
series
of
(x/y/z)
coordinates,
more
specifically,
a
cube
that
this
directly
underneath
Steve’s
feet.
Then,
we’re
going
to
query
each
block
in
the
Minecraft
world
for
its
content.
Next,
we
tabulate
the
elements
we’ve
found
and
provide
a
summary
in
the
debug
panel.
The
tutorial
is
going
to
guide
you
through
the
necessary
changes
bit
by
bit.
1. Change
the
.toString()
function
node.
I’ve
renamed
it
to
position
to
“()”
string
to
better
reflect
its
new
functionality:
8. CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
- 8 -
Optional
reading:
The
.trim
function
removes
the
invisible
trailing
“n”
from
the
player’s
position,
and
with
.split(“,”)
we
separate
out
the
x,
y
and
z
component
of
the
coordinate
into
an
array
called
pos.
Due
to
the
way
Minecraft
considers
player
positions
as
floating
point
numbers,
but
places
elements
in
discrete
blocks,
we
need
to
round
our
position
with
the
Math.round
function.
JavaScript
can
occasionally
act
a
bit
funny,
so
to
about
any
problems,
we
specifically
tell
it
to
interpret
the
character
strings
in
the
pos
array
as
floating
point
numbers
with
parseFloat.
Ultimately,
we
are
going
to
define
an
array
called
coordinates,
and
each
element
inside
coordinates
is
a
payload
with
a
string
in
parenthesis,
featuring
a
coordinate
of
the
cube
below
Steve.
Obligatory
reading:
By
returning
[coordinates]
at
the
end
of
the
function
(line
30,
note
the
[
]),
we’re
going
to
tell
Node-‐RED
to
trigger
the
next
node
for
reach
element
in
the
array.
2. Add
a
function
node
and
add
“msg.payload
=
"world.getBlock"+msg.payload+"n";”
-‐
this
simply
makes
the
overall
code
more
readable.
It
complements
each
(x,y,z)
triplet
with
the
world.getBlock
command,
followed
by
“n”;
3. Add
another
TCP
request
node
and
configure
it
exactly
like
the
one
before.
4. The
material
.toString()
function
node
adds
exactly
this
functionality:
“msg.payload
=
msg.payload.toString();”
–
add
a
debug
node
if
you
want
to
check
your
results.
A
table
with
common
elements
is
shown
in
the
figure,
from
http://minecraft.gamepedia.com/Data_values_(Pocket_Edition)
5. The
function
node
tabulation
counts
how
many
times
each
element
of
the
Minecraft
world
was
seen
in
the
5x5x5
=
125
blocks
underneath
Steve’s
feet.
Because
tabulation
is
invoked
every
time
a
new
element
is
detected,
we
need
to
make
use
of
a
Node-‐RED
trick:
The
context
variable
remembers
its
state
between
iterations.
9. CamJam! Workshop: Node-RED and controlling Minecraft with JavaScript
- 9 -
To
prevent
summing
up
of
elements
of
different
trigger
events,
we
modify
the
inject
node
with
a
topic
called
“trigger”.
If
the
tabulation
node
is
invoked
from
the
inject
button
(note
the
new
connection!),
we
delete
the
variable
by
assigning
it
the
value
undefined.
However,
if
we
invoke
the
function
from
the
material
.toString()
node,
we
make
sure
we
interpret
the
code
as
String.
If
our
table
is
still
undefined,
we
create
it
as
array,
otherwise
we
use
the
existing
one
(line
8).
If
the
ID
has
been
seen
before,
we
take
its
current
count,
otherwise
we
assign
0
(line
9).
Then
we
increase
the
count
for
this
observation
(this
event
only)
of
seeing
the
ID
(line
10).
Ultimately,
we
return
our
table
as
message.
6. To
prevent
the
printing
of
our
table
while
it
is
still
being
generated
(remember,
the
tabulation
method
gets
invoked
125
times!),
we
make
use
of
the
trigger
node.
Configure
it
with
the
following
settings:
The
node
remembers
the
first
time
it
was
triggered,
and
only
if
it
hasn’t
received
any
new
messages
for
250
milliseconds,
passes
the
information
on
to
the
final
debug
node.
7. Deploy
and
take
Steve
for
a
walk.
Trigger
the
inject
node.
Wait
patiently.
Check
the
console
and/or
debug
panel
for
output.
Does
the
output
make
sense
to
you?
Conclusions
Node-‐RED
is
an
incredibly
powerful
framework
that
allows
you
to
do
things
in
very
little
time.
The
official
directory
of
flows
donated
to
the
community
is
here
http://flows.nodered.org
and
they
can
easily
be
imported
by
copying
&
pasting
the
JSON-‐formatted
code.
Given
the
availability
of
a
convenient
input
node,
try
to
display
tweets
with
a
particular
hashtag
in
Minecraft.
You’re
going
to
be
surprised
how
simple
it
is!
There’s
a
bunch
of
other
Node-RED
tutorials
at
http://www.slideshare.net/BorisAdryan
and
occasional
Node-‐RED
tips
at
@BorisAdryan.