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

[Solved]Need help with multishell script. {READ THIS, NEED HELP}

Started by TheJebForge, 17 January 2015 - 04:43 PM
TheJebForge #1
Posted 17 January 2015 - 05:43 PM
I'm made the custom multishell script and the drawing happening very slow! I mean, to draw the Image. With the script, the computer drawing it in 2 seconds! In clean computer, the computer drawing it in >1 sec! Why can it be?
Edited on 22 January 2015 - 01:13 PM
TheJebForge #2
Posted 17 January 2015 - 05:51 PM
There is the code of custom multishell!


-- Setup process switching
local parentTerm = term.current()
local w,h = parentTerm.getSize()
local tProcesses = {}
local nCurrentProcess = nil
local nRunningProcess = nil
local bShowMenu = false
local bWindowsResized = false
local function selectProcess( n )
    if nCurrentProcess ~= n then
	    if nCurrentProcess then
		    local tOldProcess = tProcesses[ nCurrentProcess ]
		    tOldProcess.window.setVisible( false )
	    end
	    nCurrentProcess = n
	    if nCurrentProcess then
		    local tNewProcess = tProcesses[ nCurrentProcess ]
		    tNewProcess.window.setVisible( true )
		    tNewProcess.bInteracted = true
	    end
    end
end
local function setProcessTitle( n, sTitle )
    tProcesses[ n ].sTitle = sTitle
end
local function resumeProcess( nProcess, sEvent, ... )
    local tProcess = tProcesses[ nProcess ]
    local sFilter = tProcess.sFilter
    if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then
	    local nPreviousProcess = nRunningProcess
	    nRunningProcess = nProcess
	    term.redirect( tProcess.terminal )
	    local ok, result = coroutine.resume( tProcess.co, sEvent, ... )
	    tProcess.terminal = term.current()
	    if ok then
		    tProcess.sFilter = result
	    else
		    printError( result )
	    end
	    nRunningProcess = nPreviousProcess
    end
end
local function launchProcess( tProgramEnv, sProgramPath, ... )
    local tProgramArgs = { ... }
    local nProcess = #tProcesses + 1
    local tProcess = {}
    tProcess.sTitle = fs.getName( sProgramPath )
    if bShowMenu then
	    tProcess.window = window.create( parentTerm, 1, 2, w, h-1, false )
    else
	    tProcess.window = window.create( parentTerm, 1, 1, w, h, false )
    end
    tProcess.co = coroutine.create( function()
	    os.run( tProgramEnv, sProgramPath, unpack( tProgramArgs ) )
	    if not tProcess.bInteracted then
		    term.setCursorBlink( false )
		    print( "Press any key to continue" )
		    os.pullEvent( "char" )
	    end
    end )
    tProcess.sFilter = nil
    tProcess.terminal = tProcess.window
    tProcess.bInteracted = false
    tProcesses[ nProcess ] = tProcess
    resumeProcess( nProcess )
    return nProcess
end
local function cullProcess( nProcess )
    local tProcess = tProcesses[ nProcess ]
    if coroutine.status( tProcess.co ) == "dead" then
	    if nCurrentProcess == nProcess then
		    selectProcess( nil )
	    end
	    table.remove( tProcesses, nProcess )
	    if nCurrentProcess == nil then
		    if nProcess > 1 then
			    selectProcess( nProcess - 1 )
		    elseif #tProcesses > 0 then
			    selectProcess( 1 )
		    end
	    end
	    return true
    end
    return false
end

local function cullProcesses()
    local culled = false
    for n=#tProcesses,1,-1 do
	    culled = culled or cullProcess( n )
    end
    return culled
end
-- Setup the main menu
local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor
if parentTerm.isColor() then
    menuMainTextColor, menuMainBgColor = colors.yellow, colors.black
    menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray
else
    menuMainTextColor, menuMainBgColor = colors.white, colors.black
    menuOtherTextColor, menuOtherBgColor = colors.black, colors.white
end
local function redrawMenu()
if bShowMenu then
local nat = term.native()
nat.setBackgroundColor(128)
nat.setTextColor(256)
nat.setCursorPos(1,1)
nat.clearLine()
nat.write("NxOS")

if #tProcesses > 1 then
  nat.setCursorPos(50,1)
  nat.write("X")
end

end
end
local function stopProcess(nProcess)
local tProcess = tProcesses[n]
  if nCurrentProcess > nProcess then
   table.remove( tProcesses, nProcess )
   nCurrentProcess = nCurrentProcess - 1
   local tNewProcess = tProcesses[ nCurrentProcess ]
		    tNewProcess.window.setVisible( true )
		    tNewProcess.bInteracted = true
  else
   table.remove( tProcesses, nProcess )
   if nProcess > 1 then
			    nCurrentProcess = nProcess - 1
    local tNewProcess = tProcesses[ nCurrentProcess ]
    tNewProcess.window.setVisible( true )
    tNewProcess.bInteracted = true
    redrawMenu()
		    elseif #tProcesses > 0 then
			    nCurrentProcess = 1
    local tNewProcess = tProcesses[ nCurrentProcess ]
    tNewProcess.window.setVisible( true )
    tNewProcess.bInteracted = true
    redrawMenu()
		    end
  end
sleep(0.01)
end
local function resizeWindows()
    local windowY, windowHeight
    if bShowMenu then
	    windowY = 2
	    windowHeight = h-1
    else
	    windowY = 1
	    windowHeight = h
    end
    for n=1,#tProcesses do
	    local tProcess = tProcesses[n]
	    local window = tProcess.window
	    local x,y = tProcess.window.getCursorPos()
	    if y > windowHeight then
		    tProcess.window.scroll( y - windowHeight )
		    tProcess.window.setCursorPos( x, windowHeight )
	    end
	    tProcess.window.reposition( 1, windowY, w, windowHeight )
    end
    bWindowsResized = true
end
local function setMenuVisible( bVis )
    if bShowMenu ~= bVis then
	    bShowMenu = bVis
	    resizeWindows()
	    redrawMenu()
    end
end
local multishell = {}
function multishell.getFocus()
    return nCurrentProcess
end

function multishell.setFocus( n )
    if n >= 1 and n <= #tProcesses then
	    selectProcess( n )
	    redrawMenu()
	    return true
    end
    return false
end
function multishell.getTitle( n )
    if n >= 1 and n <= #tProcesses then
	    return tProcesses[n].sTitle
    end
    return nil
end
function multishell.setTitle( n, sTitle )
    if n >= 1 and n <= #tProcesses then
	    setProcessTitle( n, sTitle )
	    redrawMenu()
    end
end
function multishell.stopProcess(n)
if #tProcesses > 1 then
  stopProcess(n)
else
  err("Only 1 process there! (Press any button to con.)")
  os.pullEvent("key")
end
end
function multishell.getCurrent()
    return nRunningProcess
end
function multishell.launch( tProgramEnv, sProgramPath, ... )
if #tProcesses < 16 then
  local previousTerm = term.current()
  setMenuVisible( (#tProcesses + 1) >= 2 )
  local nResult = launchProcess( tProgramEnv, sProgramPath, ... )
  redrawMenu()
  term.redirect( previousTerm )
  return nResult
else
  err("Too many processes ran!")
  print("Press Anu Button")
  os.pullEvent("key")
end
end
function multishell.getCount()
    return #tProcesses
end
function multishell.setMenuVisible( bol )
setMenuVisible( bol )
end
-- Begin
setMenuVisible( false )
redrawMenu()
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 >= 1 )
		    redrawMenu()
	    end
    elseif sEvent == "mouse_click" then
	    -- Click event
	    local button, x, y = tEventData[2], tEventData[3], tEventData[4]
  if x >= 1 and x <= 5 and y == 1 and bShowMenu and not (tProcesses[#tProcesses].sTitle == "Manager.lua") then
  
   selectProcess( multishell.launch({
    ["shell"] = shell,
    ["multishell"] = multishell,
},"/NxOS/Core/Manager.lua"))
  end
  if x == 50 and y == 1 and bShowMenu and #tProcesses > 1 then
   stopProcess(nCurrentProcess)
  end
  -- Passthrough to current process
		    resumeProcess( nCurrentProcess, sEvent, button, x, (bShowMenu and y-1) or y )
		    if cullProcess( nCurrentProcess ) then
			    setMenuVisible( #tProcesses >= 1 )
			    redrawMenu()
		    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 >= 1 )
			    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 >= 1 )
		    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 >= 1 )
		    redrawMenu()
	    end
    end
end
-- Shutdown
term.redirect( parentTerm )

Code of Manager.lua

function p(x,y,color)
paintutils.drawPixel(x,y,color)
end
function l(x,y,endx,endy,color)
paintutils.drawLine(x,y,endx,endy,color)
end
function fg(app)
shell.switchTab(shell.openTab("test"))
end

function sCP(x,y)
term.setCursorPos(x,y)
end
function cl()
term.clear()
end
function blink(bol)
term.setCursorBlink(bol)
end
function box(x,y,endx,endy,color)
for i = 1,(endx - x + 1),1 do
  for j = 1,(endy - y + 1),1 do
   p(x - 1 + i, y - 1 + j,color)
  end
end
end
function tpr(text,x,y)
term.setCursorPos(x,y)
term.write(text)
end
function cpr(text,y)
local w,h = term.getSize()
local x = w / 2 - string.len(text) / 2
tpr(text,x,y)
end
function bg(color)
term.setBackgroundColor(color)
end
function tg(color)
term.setTextColor(color)
end
function reloadConfig()
config = {}
fil = fs.open("NxOS/Core/Data/UserPreferences.lua","r")
local temp = fil.readLine()
local t = 0
while temp do
  t = t + 1
  config[t] = temp
  temp = fil.readLine()
end
fil.close()
end
function modConfig(id,text)
config[id] = text
fil = fs.open("NxOS/Core/Data/UserPreferences.lua","w")
for i = 1, #config,1 do
  fil.writeLine(config[i])
end
fil.close()
end
box(1,1,51,18,1)
tg(32768)
tpr("ID",2,1)
tpr("Name",5,1)
-- Vars
pwm = 0
local function PwMenu()
box(2,14,11,17,256)
tg(32768)
tpr("ShutDown",3,15)
tpr("Reboot",4,16)
while true do
  local event,b,x,y = os.pullEvent()
  if event == "mouse_click" then
   if x >= 2 and x <= 11 and y <= 17 and y >= 14 and b == 1 then
    if y == 16 then
	 os.reboot()
    end
    if y == 15 then
	 os.shutdown()
    end
   else
    break
   end
  end
end

end
local function refresh()
for i = 1,16, 1 do
  l(2,i+1,50,i+1,1)
end
for i = 1, multishell.getCount() do
  l(2,i+1,50,i+1,256)
end
if pwm == 0 then
  bg(256)
  tpr("Power ^",2,18)
else
  bg(128)
  tpr("Power v",2,18)
end
bg(256)
for i = 1, multishell.getCount(),1 do
  tpr(i,2,i+1)
  tpr(multishell.getTitle(i),5,i+1)
  bg(128)
  tg(32768)
  if multishell.getTitle(i) == multishell.getTitle(multishell.getCurrent()) then
  else
   tpr("Sw.To",43,i+1)
  end
   if i > 1 then
    if multishell.getCurrent() == i then
    else
    tpr("X",49,i+1)
    end
   end
 
 
  bg(256)
  tg(32768)
end
end
refresh()
while true do
local event,b,x,y = os.pullEvent()
if event == "mouse_click" then
  if x >= 2 and x <= 13 and b == 1 then
  
  end
  if x >= 2 and x <= 8 and y == 18 and b == 1 then
   pwm = 1
   refresh()
   PwMenu()
   pwm = 0
   box(1,14,20,18,1)
   refresh()
  end
  for i = 1, multishell.getCount(),1 do
   if x == 49 and y == (i + 1) and b == 1 and i > 1  then
    if multishell.getCurrent() == i then
    else
    multishell.stopProcess(i)
    sleep(0.01)
    refresh()
    end
   end
  end
  if x >= 43 and x <= 47 and b == 1 then
  if y == 2 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 3 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 4 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 5 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 6 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 7 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 8 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 9 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 10 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 11 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 12 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 13 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 14 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 15 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 16 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  if y == 17 then
   if multishell.getCurrent() == y - 1 then
   else
   shell.switchTab(y - 1)
   return
   end
  end
  end
end
end

The code of custom functions

function p(x,y,color)
paintutils.drawPixel(x,y,color)
end
function l(x,y,endx,endy,color)
paintutils.drawLine(x,y,endx,endy,color)
end
function fg(app)
local dir = shell.dir() .. "/"
shell.run("cd /")
shell.run("fg "..app)
shell.run("cd "..dir)
end
function bbg(app)
local dir = shell.dir() .. "/"
shell.run("cd /")
shell.run("bg "..app)
shell.run("cd "..dir)
end
function sCP(x,y)
term.setCursorPos(x,y)
end
function cl()
term.clear()
end
function blink(bol)
term.setCursorBlink(bol)
end
function box(x,y,endx,endy,color)
for i = 1,(endx - x + 1),1 do
  for j = 1,(endy - y + 1),1 do
   p(x - 1 + i, y - 1 + j,color)
  end
end
end
function tpr(text,x,y)
term.setCursorPos(x,y)
term.write(text)
end
function cpr(text,y)
local w,h = term.getSize()
local x = w / 2 - string.len(text) / 2
tpr(text,x,y)
end
function bg(color)
term.setBackgroundColor(color)
end
function tg(color)
term.setTextColor(color)
end
function reloadConfig()
config = {}
fil = fs.open("NxOS/Core/Data/UserPreferences.lua","r")
local temp = fil.readLine()
local t = 0
while temp do
  t = t + 1
  config[t] = temp
  temp = fil.readLine()
end
fil.close()
end
function modConfig(id,text)
config[id] = text
fil = fs.open("NxOS/Core/Data/UserPreferences.lua","w")
for i = 1, #config,1 do
  fil.writeLine(config[i])
end
fil.close()
end
InDieTasten #3
Posted 17 January 2015 - 05:54 PM
I'm made the custom multishell script and the drawing happening very slow! I mean, to draw the Image. With the script, the computer drawing it in 2 seconds! In clean computer, the computer drawing it in <1 sec! Why can it be?
I'm not sure what exactly you are doing.
About all multishell program have their applications one layer higher which means one level lower in performance.
otherwise the applications themselves need to be compatible to the specific multishell. it's because the call is "routed" one time more often than usual. it makes drawing slow. there are even benchmarks to prove this behaviour.

OMG, please spoiler them or better put a link to a gist or pastebin(cause syntax highlighting)
TheJebForge #4
Posted 17 January 2015 - 05:55 PM
Can someone please fix my script! I'm will be very thankful!
InDieTasten #5
Posted 17 January 2015 - 06:00 PM
Can someone please fix my script! I'm will be very thankful!

Dude, you need to tell more about your actual problem. you can't expect us to be solving your problems magically without even knowing the problem
It seems rather rude to me(maybe I'm sensitive right now), that you call to us to fix your problems.

and also, if you change to container your code, please edit your title as well.
TheJebForge #6
Posted 17 January 2015 - 06:02 PM
Problem is in performance! Sorry, but I don't even understand why the performance is went down! Can you tell me why the performance is low there? Thanks, anyway…
InDieTasten #7
Posted 17 January 2015 - 06:05 PM
Problem is in performance! Sorry, but I don't even understand why the performance is went down! Can you tell me why the performance is low there? Thanks, anyway…
You stated there are two cases, which defer in their performance. Could you try to explain them in more detail? That would help the problem solving, because right now I see a ton of code, which at some point may have an issue. So when is it fast, and when is it slow?
TheJebForge #8
Posted 17 January 2015 - 06:08 PM
When I'm trying to use FOR with any visual function, the performance going down! For example, I'm trying to draw the wallpaper by paintutils.drawImage(img,x,y), the wallpaper prints in 2 seconds. But on computer where the script isn't installed the wallpaper draws in >1 sec!
Edited on 17 January 2015 - 05:09 PM
SquidDev #9
Posted 17 January 2015 - 06:15 PM
First things first your manager code has ~100 lines of identical if … elseif … statements. There is an or keyword (or you can do if y >= 17 and y <= 2 then … end).

On computers without multishell you draw like this: terminal API (term.draw) > native terminal object
On multishell you have: terminal API > window API > native terminal
On your code you have: terminal API > window API > window API > native terminal.

Multiple layers of multishell will slow slow down things a lot, though I don't see why it would take 2 seconds (ClamShell have a buffer implemented for scrolling and there is not that much performance difference).
Edited on 17 January 2015 - 05:16 PM
InDieTasten #10
Posted 17 January 2015 - 06:18 PM
Ok, I don't "really" see an issue with that. Performance loss is completely normal when switching form single-shell to multishell. Although 2 seconds are a really really long time, I wouldn't assume, that there's a solution to solve it without rewriting like the half of it.
TheJebForge #11
Posted 17 January 2015 - 06:18 PM
Ohhh! That why! Thanks! I'll try that!
TheJebForge #12
Posted 17 January 2015 - 06:24 PM
I'm tried to change nat to parentTerm (in redraw), and the performance has became a bit higher! Now the wallpaper drawing in 1,5 seconds…
But the problem hasn't gone…
Edited on 17 January 2015 - 05:26 PM
InDieTasten #13
Posted 17 January 2015 - 06:26 PM
I'm tried to change nat to parentTerm (in redraw), and the performance has became a bit higher! Now the wallpaper drawing in 1,5 seconds…
what are you measuring that with? are you on an emulator?
TheJebForge #14
Posted 17 January 2015 - 06:29 PM
Yeah, emu. (CCEMUREDUX)
InDieTasten #15
Posted 17 January 2015 - 06:31 PM
what are you measuring that with?
Edited on 17 January 2015 - 05:31 PM
TheJebForge #16
Posted 17 January 2015 - 06:32 PM
Huh?
What are you talking about?.
Edited on 17 January 2015 - 05:35 PM
InDieTasten #17
Posted 17 January 2015 - 06:35 PM
Your 1,5 Seconds. are you reading them off of something? do you use a physical clock? os.clock? http-reqests to timeservers?
TheJebForge #18
Posted 17 January 2015 - 06:37 PM
stopwatch app on my phone
TheJebForge #19
Posted 20 January 2015 - 03:47 PM
So anyone can help me?
Bomb Bloke #20
Posted 21 January 2015 - 02:39 AM
One way in which your code loses efficiency is in how you handle your "shortname" functions. Every function call your script performs takes time (this would apply even if you were calling empty functions).

For example, this:

function l(x,y,endx,endy,color)  -- l is a new function which runs the paintutils.drawLine function
paintutils.drawLine(x,y,endx,endy,color)
end
.
.
.
for i = 1, multishell.getCount() do
  l(2,i+1,50,i+1,256)  -- call l, which then calls paintutils.drawLine = 2 calls
end

… takes more time to execute than this:

for i = 1, multishell.getCount() do
  paintutils.drawLine(2,i+1,50,i+1,256)  -- just call paintutils.drawLine = 1 call
end

… because you are doubling the amount of function calls you're performing.

On the other hand, if you do this:

local l = paintutils.drawLine  -- l and paintutils.drawLine now lead to the same copy of the function stored in RAM
.
.
.
for i = 1, multishell.getCount() do
  l(2,i+1,50,i+1,256)  -- runs the drawLine function directly = 1 call
end

… it'll actually run even faster, because referencing paintutils.drawLine involves a lookup into the paintutils table - but if you save the function pointer directly into l, then calling l skips that table lookup in future!

Localising the l variable should speed things up further when you go to use it.

Edit:

Then there's this sort of thing:

function box(x,y,endx,endy,color)
for i = 1,(endx - x + 1),1 do
  for j = 1,(endy - y + 1),1 do
   p(x - 1 + i, y - 1 + j,color)  -- p calls paintutils.drawPixel()
  end
end
end

Consider what the drawPixel function does: it moves the cursor, it sets the background colour, then it draws a single space. Drawing a 10x10 box would call it a hundred times. That's a hundred times you're moving the cursor, a hundred times you're setting the background colour, and a hundred individual calls you're making to draw spaces.

Now let's say you did it like this:

function box(x,y,endx,endy,color)
	term.setBackgroundColour(color)
	for j = y, endy do
		term.setCursorPos(x, j)
		term.write(string.rep(" ", endx - x + 1))
	end
end

You'd only set the background colour once, and only trigger one cursor-move and screen-write per line.
Edited on 21 January 2015 - 02:20 AM
TheJebForge #21
Posted 22 January 2015 - 02:12 PM
Thanks! It's became more faster than I have before!
Edited on 22 January 2015 - 01:14 PM