This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
MysticT's profile picture

Sync API - Terminal-Monitor Synchronization

Started by MysticT, 20 September 2012 - 09:01 PM
MysticT #1
Posted 20 September 2012 - 11:01 PM
This api lets you use all the screens you want at the same time. You can have the output on the console and all the monitors you want at the same time. It also supports custom output targets, in case you want to send the output through rednet or something like that.

The usage is really simple:
Spoiler

sync.addTarget(target)
-- add a target to use. Works like term.redirect.
-- target: a table with the term functions.

sync.removeTarget(target)
-- removes a target.
-- target: a previoulsy added target table.

sync.addMonitor(side)
-- adds the monitor on the given side to the targets.
-- side: the side of the monitor to add.

sync.removeMonitor(side)
-- removes the monitor on the given side from the targets.
-- side: the side of the monitor to remove.

sync.addMonitors()
-- adds all the attached monitors to the targets.

sync.removeMonitors()
-- removes all the attached monitors from the targets.

sync.redirect(addTerminal)
-- redirects the terminal output to all the targets
-- addTerminal: set to true to add the default term to the targets.

sync.restore()
-- restores the output to the previous state (console, monitor or whatever)

sync.useMaxSize(:D/>/>/>
-- whether to use the maximum or minimum size of all the targets. b should be a boolean (true to use max size, false for min size).
(sync is the name of the api, ie whatever you named the file)

Example usage:
Spoiler

os.loadAPI("sync") -- load the api

sync.redirect(true) -- add the term to the targets and start syncing
print("I'm on the console")
sync.addMonitor("left") -- add the left monitor
print("I'm on the console and the left monitor")
sync.addMonitors() -- add all the monitors
print("I'm on the console and all the monitors!")
sync.restore() -- restore output
print("Back to normal output")

Download: pastebin (KhyGwUPm)
Code:
Spoiler

-- Sync API
-- Terminal-Monitor Synchronization
-- by MysticT

local tApi = {}
local tTargets = {}
local tMonitors = {}

local bMax = false
local nWidth, nHeight = 0, 0
local nCursorX, nCursorY = 1, 1
local bBlink = false
local bgColor = colors.black
local txtColor = colors.white

local function resize()
    local w, h
    for target in pairs(tTargets) do
        local _w, _h = target.getSize()
        if bMax then
            if (w == nil or h == nil) or (_w * _h) > (w * h) then
                w, h = _w, _h
            end
        else
            if (w == nil or h == nil) or (_w * _h) < (w * h) then
                w, h = _w, _h
            end
        end
    end
    if w and h then
        nWidth = w
        nHeight = h
    end
end

local function call(func, ...)
    for target in pairs(tTargets) do
        target[func](...)
    end
end

-- Sync Functions

function tApi.getSize()
    return nWidth, nHeight
end

function tApi.getCursorPos()
    return nCursorX, nCursorY
end

function tApi.setCursorPos(x, y)
    nCursorX, nCursorY = x, y
    call("setCursorPos", x, y)
end

function tApi.setCursorBlink(B)/>
    bBlink = b
    call("setCursorBlink", B)/>
end

function tApi.clear()
    call("clear")
end

function tApi.clearLine()
    call("clearLine")
end

function tApi.write(text)
    call("write", text)
    nCursorX = nCursorX + #text
end

function tApi.scroll(n)
    call("scroll", n)
end

function tApi.isColor()
    for target in pairs(tTargets) do
        if not target.isColor() then
            return false
        end
    end
    return true
end
tApi.isColour = tApi.isColor

function tApi.setBackgroundColor(c)
    bgColor = c
    call("setBackgroundColor", c)
end
tApi.setBackgroundColour = tApi.setBackgroundColor

function tApi.setTextColor(c)
    txtColor = c
    call("setTextColor", c)
end
tApi.setTextColour = tApi.setTextColor

-- API Functions

function addTarget(target)
    tTargets[target] = true
    resize()
    target.setCursorPos(nCursorX, nCursorY)
    target.setCursorBlink(bBlink)
    target.setBackgroundColor(bgColor)
    target.setTextColor(txtColor)
end

function removeTarget(target)
    tTargets[target] = nil
end

function addMonitor(sSide)
    if tMonitors[sSide] then
        return true
    end
    if peripheral.isPresent(sSide) and peripheral.getType(sSide) == "monitor" then
        local mon = peripheral.wrap(sSide)
        tMonitors[sSide] = mon
        addTarget(mon)
        return true
    end
    return false
end

function removeMonitor(sSide)
    if tMonitors[sSide] then
        removeTarget(tMonitors[sSide])
        tMonitors[sSide] = nil
    end
end

function addMonitors()
    for _,s in ipairs(rs.getSides()) do
        addMonitor(s)
    end
end

function removeMonitors()
    for _,s in ipairs(rs.getSides()) do
        removeMonitor(s)
    end
end

function useMaxSize(B)/>
    if b ~= bMax then
        bMax = b
        resize()
    end
end

function redirect(bAddTerm)
    if bAddTerm then
        addTarget(term.native or term)
    end
    term.redirect(tApi)
end

function restore()
    term.restore()
end

If you found any bugs, let me know so I can fix them.
Any feddback is appreciated.

Changelog:
- 11/3/2013: updated for CC 1.5, added color supprt
- 20/9/2012: first release
SilverSatin #2
Posted 25 September 2012 - 08:53 PM
This is by far my favorite code on the forum! I needed this so bad. Thanks A LOT !

i registered on the forum just to thank you!
MysticT #3
Posted 25 September 2012 - 10:49 PM
This is by far my favorite code on the forum! I needed this so bad. Thanks A LOT !

i registered on the forum just to thank you!
Thanks :D/>/>
I wrote this just for testing, and then turned it into an api. It took just an hour :P/>/>
Any suggestions are welcome. If you'd like some feature to be added, just tell me and I'll try to do it.
toxicwolf #4
Posted 25 September 2012 - 11:12 PM
Ever since Espen started something like this, I've been looking for a standalone version, so thanks! Do you mind if I include this in my Operating System? Credit will of course be given as usual. Thanks for this API anyway :P/>/>
MysticT #5
Posted 25 September 2012 - 11:31 PM
Ever since Espen started something like this, I've been looking for a standalone version, so thanks! Do you mind if I include this in my Operating System? Credit will of course be given as usual. Thanks for this API anyway :D/>/>
Sure, no problem. Hope to see WolfOS 1.4 soon :P/>/>
toxicwolf #6
Posted 26 September 2012 - 07:06 AM
Ever since Espen started something like this, I've been looking for a standalone version, so thanks! Do you mind if I include this in my Operating System? Credit will of course be given as usual. Thanks for this API anyway :D/>/>
Sure, no problem. Hope to see WolfOS 1.4 soon :P/>/>
Thanks :)/>/> And I hope so too, but I have so much to do and so little time!
stilldabomb #7
Posted 26 September 2012 - 07:13 AM
Haha, this is awesome MysticT! Great job!
juiceblox #8
Posted 30 September 2012 - 08:00 PM
Ok, I'm learning here. I'm hoping I can get some explanations. I have the API working beautifully, but I am curious.

1. What is the first part of the API code doing?
2. When you call a function that's in an API file, does it not just read the part of the code where the function is defined, or does it go through the entire API file?
3. What's the point of putting the term local before a function?
4. What does sync.redirect do? The example shows an input of true (to set default target as default?) and the function sets the input, true, as variable bAddterm to be wierdly used in an if statement? This whole function confuses me.
5. What is target?
MysticT #9
Posted 30 September 2012 - 08:14 PM
1. What is the first part of the API code doing?
- It defines some needed variables and functions to use later in the api.

2. When you call a function that's in an API file, does it not just read the part of the code where the function is defined, or does it go through the entire API file?
- When you use os.loadAPI (or put it in "rom/apis" to load it automatically), the whole file is loaded and the global functions and variables are saved in a table named like the api file (in this case sync).

3. What's the point of putting the term local before a function?
- It makes the function local to the api, so it can't be used from outside (for example, you can't use sync.resize because it's a local function).

4. What does sync.redirect do? The example shows an input of true (to set default target as default?) and the function sets the input, true, as variable bAddterm to be wierdly used in an if statement? This whole function confuses me.
- It redirects the terminal output (using term.redirect) to the table I defined with all the sync functions. The parameter just tells it whether the terminal/console should be added to the output targets.

5. What is target?
- It must be a table containing all the terminal functions (getSize, getCursorPos, setCursorPos, setCursorBlink, clear, clearLine, write and scroll).
toxicwolf #10
Posted 30 September 2012 - 09:10 PM
Not sure if this is an error on my behalf or not, but I've been having trouble getting the Sync API to work.

When I follow the example usage, trying to add the first monitor causes the computer to shutdown without an error message. Trying to add the monitor to the target list before the sync.redirect(true) call throws the following error:
sync:33: Invalid monitor setup
Hope you can help me :)/>/>
MysticT #11
Posted 30 September 2012 - 10:00 PM
Not sure if this is an error on my behalf or not, but I've been having trouble getting the Sync API to work.

When I follow the example usage, trying to add the first monitor causes the computer to shutdown without an error message. Trying to add the monitor to the target list before the sync.redirect(true) call throws the following error:
sync:33: Invalid monitor setup
Hope you can help me :)/>/>
Well, there's nothing I can do about it. It's been reported before as a bug, not sure what causes it, but I think it has something to do with chunk boundaries, so try moving the monitor so it's inside the same chunk.
Have you tried using the monitor without the api?
toxicwolf #12
Posted 01 October 2012 - 05:09 PM
Not sure if this is an error on my behalf or not, but I've been having trouble getting the Sync API to work.

When I follow the example usage, trying to add the first monitor causes the computer to shutdown without an error message. Trying to add the monitor to the target list before the sync.redirect(true) call throws the following error:
sync:33: Invalid monitor setup
Hope you can help me :)/>/>
Well, there's nothing I can do about it. It's been reported before as a bug, not sure what causes it, but I think it has something to do with chunk boundaries, so try moving the monitor so it's inside the same chunk.
Have you tried using the monitor without the api?
Not sure why, but it all works fine now.. Perhaps updating to the latest Forge version and the CC 1.43pr1 helped in some way? Not sure exactly what I did different, but it now works.
Cranium #13
Posted 01 October 2012 - 05:24 PM
Not sure why, but it all works fine now.. Perhaps updating to the latest Forge version and the CC 1.43pr1 helped in some way? Not sure exactly what I did different, but it now works.

MAGIC
toxicwolf #14
Posted 12 October 2012 - 04:10 PM
Just to let you know, this doesn't work properly with the new CC v1.45 beta. It is missing the colour related functions.
MysticT #15
Posted 12 October 2012 - 10:57 PM
Just to let you know, this doesn't work properly with the new CC v1.45 beta. It is missing the colour related functions.
Yeah I'll update it when I have a chance. Not a priority to me now, so might take some time. Also, 1.45 is just a beta, so maybe it's better to wait for the release (in case something changes).
toxicwolf #16
Posted 13 October 2012 - 01:48 PM
Just to let you know, this doesn't work properly with the new CC v1.45 beta. It is missing the colour related functions.
Yeah I'll update it when I have a chance. Not a priority to me now, so might take some time. Also, 1.45 is just a beta, so maybe it's better to wait for the release (in case something changes).
No worries, was just giving you the heads up. I've already done a kind of un-official update of my local copy and it works fine. But waiting for the full 1.45 release before officially updating Sync API is a good idea.
fattigfaan #17
Posted 17 October 2012 - 11:18 AM
Is there a way i can set the monitor size?
I have mine at like 8*5 atm, but I'm not sure how to get it to stretch.
It works fine if i run it on the monitor outside the API though.
MysticT #18
Posted 17 October 2012 - 05:39 PM
Is there a way i can set the monitor size?
I have mine at like 8*5 atm, but I'm not sure how to get it to stretch.
It works fine if i run it on the monitor outside the API though.
By default it uses the smallest size of all the targets (console and monitors), but you can change that behaviour with useMaxSize (I forgot to include it in the usage :D/>/>, added now).
Example:

sync.addMonitor("left") -- add the monitor on the left
sync.useMaxSize(true) -- use maximum size, so all the monitor is used
sync.redirect(true) -- add the terminal and redirect.
print("This is on the monitor and the console. It should use the whole monitor width for this text...")
sync.useMaxSize(false) -- use minimum size
print("This is also on the monitor and the console, but it should use the console size now...")
fattigfaan #19
Posted 17 October 2012 - 07:03 PM
When using that, the console text moves outside, but i can see it come up on the monitors behind. So it's not limited by the console =s
MysticT #20
Posted 17 October 2012 - 08:33 PM
When using that, the console text moves outside, but i can see it come up on the monitors behind. So it's not limited by the console =s
Well, it can only use one size. So, it's either the console or the monitor…
It would be too hard to use multiple sizes, and it would probably break the default print/write functions, so I don't think I'll change it.
fattigfaan #21
Posted 17 October 2012 - 08:58 PM
Aah okay =) then I'll just resize my monitor =3
Sp1rit #22
Posted 08 January 2013 - 06:30 AM
Thx for this. Its great. I didnt know term.redirect exists i used to write on monitor and term separately :P/>

It is missing the color functions for advanced computers. I added them by myself but maybe others could use them too. ^^
bjornir90 #23
Posted 09 January 2013 - 07:43 AM
Really cool ! Don't know it was possible
1vannn #24
Posted 12 March 2013 - 10:40 AM
This is broken in the newest version of ComputerCraft, (1.5pr3)
MysticT #25
Posted 12 March 2013 - 01:25 PM
Ok, I finally updated it to support color. It was a really simple change (adding the missing functions), but it had to be done for it to work.
Download is the same, enjoy it.
TCGM #26
Posted 11 April 2014 - 08:10 AM
I tried loading in the pastebin version, then using the exact same example usage code you used in your main post (except I replaced "left" with "monitor_0"). restore and redirect both error out with "sync:19:attempt to index ? (a function value)". I should note that the monitors I am trying to connect to monitors attached via Wired Modems and Networking Cables.
Wojbie #27
Posted 11 April 2014 - 09:20 AM
I tried loading in the pastebin version, then using the exact same example usage code you used in your main post (except I replaced "left" with "monitor_0"). restore and redirect both error out with "sync:19:attempt to index ? (a function value)". I should note that the monitors I am trying to connect to monitors attached via Wired Modems and Networking Cables.
Are you using version of Computercraft 1.6 of later? IF yes then changes in Computercraft broke this api. Sorry.
apemanzilla #28
Posted 11 April 2014 - 11:11 AM
And plus this stuff is more than a year old anyways so some other update could've broken compatibility long before.
TCGM #29
Posted 11 April 2014 - 05:09 PM
Yeah, using the 1.6.2 update of CC. Any alternatives out there?
apemanzilla #30
Posted 13 April 2014 - 12:56 AM
Yeah, using the 1.6.2 update of CC. Any alternatives out there?
I'm sure it shouldn't be too difficult to write a redirect object that sends commands to the main window and a monitor…