-
Notifications
You must be signed in to change notification settings - Fork 0
Client
The client API is used by the turtles themselves in order to actually display the visuals requested by the server.
Note
Many methods are still private, so they will not be documented here yet. I will be making more of them available as I refactor some things.
Here is a brief explanation of most of the public fields, as they are mostly
self-explanatory. position
and blocks_used
require a bit more explanation,
and are covered in their own sub-section below.
-
array_style
: The style of array the turtles are in, either"horizontal"
or"vertical"
. -
font
: The font the turtles are using to display characters, loaded from the disk drive. This is a 2-layer table that maps[y][x]
to a boolean value, wheretrue
is foreground andfalse
is background. -
color_map
: The positions within the turtle's inventory each color of block should be in. -
current_color
: The current color the turtle has placed (or nil, if none). -
color_want
: The color the turtle wants to place, but hasn't yet (i.e: the turtle is currently working on placing another color, but the server told it to draw a new color instead). This color will be drawn on the next redraw tick. -
guideblock_top
: In horizontal Turmitors, this is the block that the turtles will look for and treat as the "top" side of the array. Defaults tominecraft:polished_andesite
. -
guideblock_left
: In horizontal Turmitors, this is the block that the turtles will look for and treat as the "left" side of the array. Defaults tominecraft:polished_diorite
. -
control_channel
: The channel that this specific turtle is listening on for control messages from the server. -
is_bottom_right_corner
: A boolean value containing whether or not the turtle is in the bottom right corner of the array. This is only used so that the turtle that is at the bottom right corner of the array can report back its position when the server requests the size of the array, as the bottom-right turtle will have a position that is the size of the array. -
frozen
: A boolean value that, when true, will prevent the turtle from drawing anything. The turtle however can still pick up the block while frozen, it just cannot place anything new (and as such will ignore placement orders, unless the order is specifically ONLY to pick up the block).
{
["block_name"] = colors.x,
...
}
The blocks_used
field is a table that contains the blocks the turtle will use
to draw the screen. The key is the block name, and the value is the color of the
block it should be placed as. This is used to determine what block to place when
the server tells the turtle to draw a pixel.
{
x: number,
y: number,
char_x: number,
char_y: number,
inner_x: number,
inner_y: number
}
The position
field is a table that contains the turtle's x
and y
location,
as well as the x and y position of the character they are a representative of,
and the position within that character the turtle is. The x
and y
values are
1-indexed, while character and inner positions are 0-indexed.
For example, a turtle at position x: 3, y: 3
would be the turtle representing
the character at the very top left (0, 0), so the char_x
and char_y
values
would be 0. However, within that character, the turtle is at position 3,3, so
the inner_x
and inner_y
values would be 2.
Similarly, a turtle at position x: 11, y: 15
would be the turtle representing
the character diagonal down and to the right of the top left character (since
the characters are 6x9), so the char_x
and char_y
values would be 1, 1. To
determine the inner_x
and inner_y
values, you just subtract one then
modulo the x
and y
values by the size of the characters. In this case, they
would be 4, 5.
The char_x
and char_y
values are later used to determine the channels used
for controlling the turtle, see the Shared Documentation page for more
information on how those are determined.
The inner_x
and inner_y
values are used when the turtles are told to display
a character. The server just sends an offset position to the turtle, and the
turtle "looks" at that offset position, then offsets it again by its inner_x
and inner_y
values to determine what specific pixel to draw.
Let's say we are the turtle at position 3,5, and the server wants the character
we are a part of to draw the letter F
. The server would send all turtles in
the character the following message:
{
action = "character",
data = {
offset_x = 50,
offset_y = 46,
fg = colors.white,
bg = colors.black,
}
}
The offset values are the offset positions of the top left corner of the
character in the font -- in this case, 50 and 46 (See the
Server Documentation page for more information on how the server
calculates this). The turtle will then add its own inner_x
and inner_z
offset to this value to determine what pixel to draw. In this case, the turtle
would draw the pixel at position 52,50 of the font.
Sets the position of the turtle in the grid. This calculates the char_x
,
char_y
, inner_x
, and inner_y
values based on the x
and y
values
provided, as well as determines the control channel for the turtle based on the
char_x
and char_y
values.
char_x = math.floor((x - 1) / 6)
char_y = math.floor((y - 1) / 9)
inner_x = (x - 1) % 6
inner_y = (y - 1) % 9
control_channel = TurmitorChannels.get_client_channel(
char_x,
char_y
)
Note that this method does not actually open or close the channels, it just sets the values.
Returns the current position of the turtle in the grid.
Determines the turtle's position using one of the below algorithms:
The algorithm for vertical Turmitors is simple, the only rules are as follows:
- If there is no turtle above and to the right of us, we are at 1,1.
- If there is no turtle above us, but there is one to the left of us, then we
are at position ?,1. We determine what
x
position we are at by waiting until the turtle to our right knows its position, then we are atx + 1, 1
. - If there is no turtle to the left of us, but there is one above us, then we
are at position 1,?. We determine what
y
position we are at by waiting until the turtle above us knows its position, then we are at1, y + 1
. - If there is a turtle above and to the right of us, then we wait until either
of the turtles know what position they are at. Then, if the turtle to our
right knows its position, we are at
x + 1, y
. If the turtle above us knows its position, we are atx, y + 1
.
The algorithm for horizontal Turmitors is a bit more complex, as the turtles in the center of the array have no concept of up, down, left, or right. Thus, the algorithm is as follows:
- If a top guideblock is found, and a left guideblock is found, then we are at position 1,1.
- If a top guideblock is found, but there is a turtle to its left, then we are
at position ?,1. We determine what
x
position we are at by waiting until the turtle to the guideblock's left knows its position, then we are atx + 1, 1
. - If a left guideblock is found, but there is a turtle to its right, then we
are at position 1,?. We determine what
y
position we are at by waiting until the turtle to the right of the guideblock knows its position, then we are at1, y + 1
. - Here is where it gets a bit complicated. If no guideblocks are found, then
we must wait until any turtle knows its position. From there, we must wait
until either the turtle to its left or the turtle to its right knows its
position. From there, we can take the largest value from each turtle and
our position will be
largest_x, largest_y
. The reason this works is due to the way the positions will propagate through the array.
Sets the color_want
value to the color provided, and kickstarts the redraw
process if it isn't already running.
Runs the Turmitor client, handling loading data, collecting blocks, determining position, listening for messages, and drawing the characters.
The turtles listens for specific actions from the server and acts on them, as follows:
-
character
: The turtle will draw the pixel at the offset provided by the server. -
place-batch
: The turtle will check if its position is within the batch provided by the server, and if so, it will place the color provided by the server. Useful for sprites and other large images. -
place
: The turtle will check if its position is that of the position provided by the server, and if so, it will place the color provided by the server. Useful for single-pixel changes.
-
clear
: All turtles place the provided color of block. -
reset
: All turtles delete their data and shut down. -
get-size
: If the turtle is at the bottom right corner of the array, it will send back its position to the server. -
pickup
: All turtles pick up the block in front of them. -
freeze
: All turtles freeze, preventing them from placing any blocks, they can still act on thepickup
command, however, making this a suitable series of commands to use if you want to reset the turtles (freeze -> pickup -> reset). -
thaw
: All turtles thaw, allowing them to place blocks again.
The redraw process is very simple, and is as follows:
- When we receive an update, resume the process by queueing the event
"turmitorclient-queue-block"
- While we have a color we want to place, destroy the block in front and place the new block. Since this takes about a quarter-second, we can receive another color to place before we finish placing the current color, hence why we loop here instead of waiting for another resume.