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

Top level multishell/bios override

Started by Hiran, 03 October 2014 - 11:13 AM
Hiran #1
Posted 03 October 2014 - 01:13 PM
When I started playing with PDA I've got irritated by one thing - 1 pda per one active program. If i want to have Door lock, turtle control and my base control thats already 3 devices in my inventory, and for me its way too much. Why 3 devices? Events are (almost) shell specific
Spoiler213 - 303 in multishell

-- Begin
parentTerm.clear()
setMenuVisible( false )
selectProcess( launchProcess( {
    ["shell"] = shell,
    ["multishell"] = multishell,
}, "/rom/programs/shell" ) )
redrawMenu()
-- Run processes
while #tProcesses > 0 do
    -- Get the event
    local tEventData = { os.pullEventRaw() }
    local sEvent = tEventData[1]
    if sEvent == "term_resize" then
	    -- Resize event
	    w,h = parentTerm.getSize()
	    resizeWindows()
	    redrawMenu()
    elseif sEvent == "char" or sEvent == "key" or sEvent == "paste" or sEvent == "terminate" then
	    -- Keyboard event
	    -- Passthrough to current process
	    resumeProcess( nCurrentProcess, unpack( tEventData ) )
	    if cullProcess( nCurrentProcess ) then
		    setMenuVisible( #tProcesses >= 2 )
		    redrawMenu()
	    end
    elseif sEvent == "mouse_click" then
	    -- Click event
	    local button, x, y = tEventData[2], tEventData[3], tEventData[4]
	    if bShowMenu and y == 1 then
		    -- Switch process
		    local tabStart = 1
		    for n=1,#tProcesses do
			    tabEnd = tabStart + string.len( tProcesses[n].sTitle ) + 1
			    if x >= tabStart and x <= tabEnd then
				    selectProcess( n )
				    redrawMenu()
				    break
			    end
			    tabStart = tabEnd + 1
		    end
	    else
		    -- Passthrough to current process
		    resumeProcess( nCurrentProcess, sEvent, button, x, (bShowMenu and y-1) or y )
		    if cullProcess( nCurrentProcess ) then
			    setMenuVisible( #tProcesses >= 2 )
			    redrawMenu()
		    end
	    end
    elseif sEvent == "mouse_drag" or sEvent == "mouse_scroll" then
	    -- Other mouse event
	    local p1, x, y = tEventData[2], tEventData[3], tEventData[4]
	    if not (bShowMenu and y == 1) then
		    -- Passthrough to current process
		    resumeProcess( nCurrentProcess, sEvent, p1, x, (bShowMenu and y-1) or y )
		    if cullProcess( nCurrentProcess ) then
			    setMenuVisible( #tProcesses >= 2 )
			    redrawMenu()
		    end
	    end
    else
	    -- Other event
	    -- Passthrough to all processes
	    local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event
	    for n=1,nLimit do
		    resumeProcess( n, unpack( tEventData ) )
	    end
	    if cullProcesses() then
		    setMenuVisible( #tProcesses >= 2 )
		    redrawMenu()
	    end
    end
    if bWindowsResized then
	    -- Pass term_resize to all processes
	    local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event
	    for n=1,nLimit do
		    resumeProcess( n, "term_resize" )
	    end
	    bWindowsResized = false
	    if cullProcesses() then
		    setMenuVisible( #tProcesses >= 2 )
		    redrawMenu()
	    end
    end
end
So if you try run 2 programs with parallel, and both are using mouse events things will get messy. But if u run them with multishell everything should work almost ok, but if they use some custom events you will still have mess.
After digging through the code ive found in bios.lua (lines 555-570) piece of code that's responsible for my suffering.

-- Run the shell
local ok, err = pcall( function()
    parallel.waitForAny(
	    function()
		    if term.isColour() then
			    os.run( {}, "rom/programs/advanced/multishell" )
		    else
			    os.run( {}, "rom/programs/shell" )
		    end
		    os.run( {}, "rom/programs/shutdown" )
	    end,
	    function()
		    rednet.run()
	    end )
end )
And the main question: how to override it? I dont want to call 'multishell' from "rom/programs/advanced/" but my own version. Is it possible to shut everything down, and then start my own environment?
theoriginalbit #2
Posted 03 October 2014 - 02:46 PM
Indeed it is very possible to do it

Link 1
Link 2
Link 3

I cannot confirm that last link, but the first two work nicely, I have used them before. There is an extensive discussion in the first link as to why (or why not) you should use this approach.
Edited on 03 October 2014 - 03:09 PM
MKlegoman357 #3
Posted 03 October 2014 - 02:50 PM
I don't understand one thing: what's wrong with multishell exactly and at what circumstances it fails to you?
Bomb Bloke #4
Posted 03 October 2014 - 03:39 PM
When running multiple scripts via multishell, you've got one script visible in the foreground, and all the others invisible in the background. All of these scripts run at the same time.

Because you would only "expect" the foreground script to respond to user input, some events are not passed to background scripts. Examples include key, char, mouse_click etc events.

It sounds like Hiran wants to set up something similar, but with a different selection of events being filtered. Personally, I'd aim to code the scripts such that they can't interfere with each other, but I realise this isn't always viable/worthwhile.
MKlegoman357 #5
Posted 03 October 2014 - 05:05 PM
From my understanding, Hiran has 2 or more programs firing the same custom event, thus interfering with each other. If that is the case, I would change those events in a way that programs would not interfere with each other.

I would really like to know the reason why you, Hiran, want to run your own multitasking shell.
Edited on 03 October 2014 - 03:06 PM
Hiran #6
Posted 03 October 2014 - 05:14 PM
Bomb Bloke is right. If u're the only one writing all the code that would be run on one device you can easily set it in a way that wont interfere with others, but if you want to use multishell to run few apps from different people you can expect miracles if they use events that are considered "global" by current multishell xD
And multishell has this "tab selection row" on the top of the screen. If i were to run some app that has button/etc on the bottom, it is outside of the screen, so essentially invisible.

I dont know if its possible, but i want to create multishell without that tab row, as it interferes with other soft, and that forces me to play with events a little, so i can add a way to change active tab without running parallel on each shell. Maybe ill add customizable event handling, im not really sure yet.

I know that its a lot of work for a little effect, but i want to learn Lua, and coding stuff in CC is a good way to learn it, and other people may find it useful :)/>

Edit:
I would really like to know the reason why you, Hiran, want to run your own multitasking shell.
I want to learn Lua the hard way, and besides are you always the owner of the code ure using, and are the apps always simple? PDA are new, and im sure that people will create more and more complex apps on them. What would you do if you have 2 really complex apps and they fire events that interfere with each other?
Lua isnt really that complex language, so i want to create something complex, maybe it will evolve in something OS like, i dont know :)/>
Edited on 03 October 2014 - 03:21 PM
MKlegoman357 #7
Posted 03 October 2014 - 05:31 PM
Ah, I see now.

I don't know if you have seen it or not, but because of the top row multishell has in CC 1.6+ there was added a new event called "term_resize" which is fired when the screen size changes (when the mutlishell top row appears). Also, there is a multishell API which lets you to open new tabs and change their title.