if this can help this is all my code
local gotTerminate=false
local activeRoutines = { }
local eventAssignments = { }
local entryRoutine
local rootRoutine
local passEventTo=nil
local numActiveCoroutines=0
local isRunning=false
local function findCoroutine(co)
for _,routine in pairs(activeRoutines) do
if routine.co==co then
return routine
end
end
return nil
end
function findNamedCoroutine(name)
return activeRoutines[name]
end
function running()
return findCoroutine(coroutine.running())
end
local function validateCaller(funcName)
local callingRoutine=running()
if callingRoutine==nil then
error(funcName.." can only be called by a coroutine running under goroutine!")
end
return callingRoutine
end
function assignEvent(assignTo,event,...)
--get the routine calling this funciton
local callingRoutine=validateCaller("assignEvent")
if callingRoutine~=entryRoutine then
return false, "assignEvent: only main routine, passed to run(..), can assign events!"
end
--get the assignee
local assignee=callingRoutine
if assignTo~=nil and assignTo~=callingRoutine.name then
assignee=findNamedCoroutine(assignTo)
if assignee==nil then
return false, "assignEvent: named coroutine not found!"
end
end
--is this event already assigned elsewhere?
if eventAssignments[event]~=nil then
return false,"This event assignment conflicts with an existing assignment!"
end
--still here? good, no conflict then
eventAssignments[event]={co=assignee,assignedBy=callingRoutine}
return true
end
function passEvent(passTo)
if passTo==nil then
passEventTo=""
else
passEventTo=passTo
end
end
function releaseEvent(event)
local callingRoutine=validateCaller("releaseEvent")
local ass=eventAssignments[event]
if ass~=nil then
if caller.co~=entryRoutine and caller~=ass.assignedBy and caller~=ass.routine then
return false, "Event can only be released by the assigner, assignee, or the entry routine!"
end
table.remove(eventAssignments,i)
return true
end
return false
end
--called by goroutines to wait for an event to occur with some
--set of optional event parameter filters
function waitForEvent(event,...)
co=validateCaller("waitForEvent")
co.filters={event,...}
return coroutine.yield("goroutine_listening")
end
local function matchFilters(params,routine)
if params[1]=="terminate" then
return true
end
for j=1,#params do
if routine==nil or (routine.filters and routine.filters[j]~=nil and routine.filters[j]~=params[j]) then
return false
end
end
return true
end
local function sendEventTo(routine, params)
if routine.dead then
return
end
term.redirect(routine.redirect)
local succ,r1=coroutine.resume(routine.co,unpack(params))
term.restore()
--did it die or terminate?
if succ==false or coroutine.status(routine.co)=="dead" then
--it's dead, remove it from active
--if there's an error, send coroutine_error
if r1~=nil then
os.queueEvent("coroutine_error",routine.name,r1)
end
--send coroutine_end
routine.dead=true
--not dead, is it waiting for an event?
else
--"goroutine_listening" indicates it yielded via coroutine.waitForEvent
--which has had filters set already
if r1~="goroutine_listening" then
--Add to eventListeners
routine.filters={r1}
end
end
end
local function _spawn(name,method,redirect,parent,args)
if activeRoutines[name] then
return nil, "Couldn't spawn; a coroutine with that name already exists!"
end
local routine={name=name,co=coroutine.create(method),redirect=redirect, parent=parent,children={}}
if routine.co==nil then
error("Failed to create coroutine '"..name.."'!")
end
parent.children[#parent.children+1]=routine
activeRoutines[name]=routine
os.queueEvent("coroutine_start",name)
numActiveCoroutines=numActiveCoroutines+1
--run it a bit..
sendEventTo(routine,args)
return routine
end
function spawnWithRedirect(name,method,redirect,...)
return _spawn(name,method,redirect,running(),{...})
end
local mon=peripheral.wrap("right")
function spawn(name,method,...)
local cur=running()
return _spawn(name,method,cur.redirect,cur,{...})
end
local nilRedir = {
write = function() end,
getCursorPos = function() return 1,1 end,
setCursorPos = function() end,
isColor = function() return false end,
scroll = function() end,
setCursorBlink = function() end,
setTextColor = function() end,
getTextColor = function() end,
getTextSize = function() end,
setTextScale = function() end,
clear = function() end,
clearLine = function() end,
}
function spawnBackground(name,method,...)
return _spawn(name,method,nilRedir,rootRoutine,{...})
end
function spawnPeer(name,method,...)
local cur=running()
return _spawn(name,method,cur.redirect,cur.parent,{...})
end
function spawnPeerWithRedirect(name,method,redirect,...)
local cur=running()
return _spawn(name,method,redirect,cur.parent,{...})
end
function spawnProgram(name,progName,...)
local cur=running()
return _spawn(name, function(...) os.run({}, ...) end,cur.redirect,cur,{...})
end
function list()
local l={}
local i=1
for name,_ in pairs(activeRoutines) do
l[i]=name
i=i+1
end
return l
end
function kill(name)
local routine=validateCaller("killCoroutine")
if not routine then
return false, "Must be called from a coroutine. How'd you even manage this?"
end
local target=findNamedCoroutine(name)
if target then
if routine==target then
return false,"You can't commit suicide!"
end
--mark it dead
routine.dead=true
return true
end
return false, "coroutine not found"
end
local function logCoroutineErrors()
while true do
local _, name, err=os.pullEventRaw("coroutine_error")
if _~="terminate" then
local file=fs.open("go.log","a")
file.write("coroutine '"..tostring(name).."' crashed with the following error: "..tostring(err))
file.close()
end
end
end
function run(main,terminable,...)
if isRunning then
--spawn it
local cur=running()
local name="main"
local i=1
while activeRoutines[name] do
i=i+1
name="main"..i
end
if _spawn(name,main,cur.redirect,cur,{...}) then
--wait for it to die
while true do
local e={os.pullEventRaw()}
if e[1]=="coroutine_end" and e[2]==name then
return
elseif e[1]=="coroutine_error" and e[2]==name then
error(e[3])
return
end
end
else
error("Couldn't spawn main coroutine "..name.."!")
end
end
--make the object for the root coroutine (this one)
rootRoutine={
co=coroutine.running(),
name="root",
redirect=term.native,
parent=nil,
children={}
}
isRunning=true
--default terminable to true
if terminable==nil then
terminable=true
end
--start the main coroutine for the process
entryRoutine=_spawn("main",main,term.native,rootRoutine,{...})
--begin with routine 1
--gooo!
local params={}
while numActiveCoroutines>0 do
--grab an event
params={os.pullEventRaw()}
if terminable and params[1]=="terminate" then
gotTerminate=true
end
local assigned=eventAssignments[params[1]]~=nil
local assignedTo=assigned and eventAssignments[params[1]].co or nil
local alreadyHandledBy={}
--set passTo to empty string, meaning anyone listening
passEventTo=""
while assignedTo~=nil do
--set this to nil first
passEventTo=nil
--send to assigned guy, if he matches, else break
if matchFilters(params,assignedTo) then
sendEventTo(assignedTo,params)
else
passEventTo=""
break
end
--add him to the list of guys who've handled this already
alreadyHandledBy[assignedTo]=true
--set assignedTo to whatever passTo was
if passEventTo=="" then
assignedTo=nil
elseif passEventTo~=nil then
assignedTo=findNamedCoroutine(passEventTo)
else
assignedTo=nil
end
end
--if it was assigned to nobody, or they passed to everybody..
if passEventTo=="" then
for _,routine in pairs(activeRoutines) do
--if they haven't handled it already via assignments above..
if not alreadyHandledBy[routine] and not routine.dead then
local match=matchFilters(params,routine)
--if it matched, or this routine has never run...
if match then
sendEventTo(routine,params)
end
end
end
end
--clean up any dead coroutines
local dead={}
local function listChildren(routine,list)
for i=1,#routine.children do
if not routine.children[i].dead then
list[routine.children[i].name]=routine.children[i]
listChildren(routine.children[i],list)
end
end
end
for name,routine in pairs(activeRoutines) do
if routine.dead then
dead[name]=routine
listChildren(routine,dead)
end
end
for name,routine in pairs(dead) do
os.queueEvent("coroutine_end",routine.name)
activeRoutines[name]=nil
numActiveCoroutines=numActiveCoroutines-1
local parent=routine.parent
if not parent.dead then
--find and remove from children
for i=1,#parent.children do
if parent.children[i]==routine then
table.remove(parent.children,i)
break
end
end
end
end
--release all events assigned to dead coroutines
local remove={}
for k,v in pairs(eventAssignments) do
if dead[eventAssignments[k].co.name] then
table.insert(remove,k)
end
end
for i=1,#remove do
eventAssignments[remove[i]]=nil
end
end
--Should I send every remaining process a terminate event, regardless
--of what they were waiting on, so they can do cleanup? Could cause
--errors in some cases...
--[[
for k,v in activeRoutines do
coroutine.resume(v.co,"terminate")
end
--]]
activeRoutines={}
eventAssignments = { }
passEventTo=nil
entryRoutine=nil
rootRoutine=nil
isRunning=false
end
function launch(sh)
if not isActive then
sh=sh or "rom/programs/shell"
term.clear()
term.setCursorPos(1,1)
run(
function()
spawnBackground("errLogger",logCoroutineErrors)
os.run({},sh)
end
)
os.shutdown()
end
end
local redirectBufferBase = {
write=
function(buffer,...)
local cy=buffer.curY
if cy>0 and cy<=buffer.height then
local text=table.concat({...}," ")
local cx=buffer.curX
local px, py
if buffer.isActive and not buffer.cursorBlink then
px,py=term.native.getCursorPos()
term.native.setCursorPos(cx+buffer.scrX, cy+buffer.scrY)
end
for i=1,#text do
if cx<buffer.width then
buffer[cy][cx]={char=string.char(text:byte(i)),textColor=buffer.textColor,backgroundColor=buffer.backgroundColor}
end
cx=cx+1
end
buffer.curX=cx
buffer[cy].isDirty=true
if buffer.isActive then
buffer.drawDirty()
if not buffer.cursorBlink then
term.native.setCursorPos(px,py)
end
end
end
end,
setCursorPos=
function(buffer,x,y)
buffer.curX=x
buffer.curY=y
if buffer.isActive and buffer.cursorBlink then
term.native.setCursorPos(x+buffer.scrX-1,y+buffer.scrY-1)
end
end,
getCursorPos=
function(buffer)
return buffer.curX,buffer.curY
end,
scroll=
function(buffer,offset)
for j=1,offset do
local temp=table.remove(buffer,1)
table.insert(buffer,temp)
for i=1,#temp do
temp[i].char=" "
temp[i].textColor=buffer.textColor
temp[i].backgroundColor=buffer.backgroundColor
end
end
if buffer.isActive then
term.redirect(term.native)
buffer.copy()
term.restore()
end
end,
isColor=
function(buffer)
return buffer._isColor
end,
isColour=
function(buffer)
return buffer._isColor
end,
clear=
function(buffer)
for y=1,buffer.height do
for x=1,buffer.width do
buffer[y][x]={char=" ",textColor=buffer.textColor,backgroundColor=buffer.backgroundColor}
end
end
if buffer.isActive then
term.redirect(term.native)
buffer.copy()
term.restore()
end
end,
clearLine=
function(buffer)
local line=buffer[buffer.curY]
local fg,bg = buffer.textColor, buffer.backgroundColor
for x=1,buffer.width do
line[x]={char=" ",textColor=fg,backgroundColor=bg}
end
buffer[buffer.curY].isDirty=true
if buffer.isActive then
buffer.drawDirty()
end
end,
setCursorBlink=
function(buffer,onoff)
buffer.cursorBlink=onoff
if buffer.isActive then
term.native.setCursorBlink(onoff)
if onoff then
term.native.setCursorPos(buffer.curX,buffer.curY)
end
end
end,
getSize=
function(buffer)
return buffer.width, buffer.height
end,
setTextColor=
function(buffer,color)
buffer.textColor=color
if buffer.isActive then
if term.native.isColor() or color==colors.black or color==colors.white then
term.native.setTextColor(color)
end
end
end,
setTextColour=
function(buffer,color)
buffer.textColor=color
if buffer.isActive then
if term.native.isColor() or color==colors.black or color==colors.white then
term.native.setTextColor(color)
end
end
end,
setBackgroundColor=
function(buffer,color)
buffer.backgroundColor=color
if buffer.isActive then
if term.native.isColor() or color==colors.black or color==colors.white then
term.native.setBackgroundColor(color)
end
end
end,
setBackgroundColour=
function(buffer,color)
buffer.backgroundColor=color
if buffer.isActive then
if term.native.isColor() or color==colors.black or color==colors.white then
term.native.setBackgroundColor(color)
end
end
end,
resize=
function(buffer,width,height)
if buffer.width~=width or buffer.height~=height then
local fg, bg=buffer.textColor, buffer.backgroundColor
if width>buffer.width then
for y=1,buffer.height do
for x=#buffer[y]+1,width do
buffer[y][x]={char=" ",textColor=fg,backgroundColor=bg}
end
end
end
if height>buffer.height then
local w=width>buffer.width and width or buffer.width
for y=#buffer+1,height do
local row={}
for x=1,width do
row[x]={char=" ",textColor=fg,backgroundColor=bg}
end
buffer[y]=row
end
end
buffer.width=width
buffer.height=height
end
end,
copy=
function(buffer,sx,sy,dx, dy, width,height)
sx=sx or 1
sy=sy or 1
dx=dx or buffer.scrX
dy=dy or buffer.scrY
width=width or buffer.width
height=height or buffer.height
local h=sy+height>buffer.height and buffer.height-sy or height-1
for y=0,h do
local row=buffer[sy+y]
local x=0
local cell=row[sx]
local fg,bg=cell.textColor,cell.backgroundColor
local str=""
local tx=x
while true do
str=str..cell.char
x=x+1
if x==width or sx+x>buffer.width then
break
end
cell=row[sx+x]
if cell.textColor~=fg or cell.backgroundColor~=bg then
--write
term.setCursorPos(dx+tx,dy+y)
term.setTextColor(fg)
term.setBackgroundColor(bg)
term.write(str)
str=""
tx=x
fg=cell.textColor
bg=cell.backgroundColor
end
end
term.setCursorPos(dx+tx,dy+y)
term.setTextColor(fg)
term.setBackgroundColor(bg)
term.write(str)
end
end,
drawDirty =
function(buffer)
term.redirect(term.native)
for y=1,buffer.height do
if buffer[y].isDirty then
term.redirect(term.native)
buffer.copy(1,y,buffer.scrX,buffer.scrY+y-1,buffer.width,buffer.height)
term.restore()
buffer[y].isDirty=false
end
end
term.restore()
end,
makeActive =
function(buffer,posX, posY)
posX=posX or 1
posY=posY or 1
buffer.scrX=posX
buffer.scrY=posY
term.redirect(term.native)
buffer.copy(1,1,posX,posY,buffer.width,buffer.height)
term.setCursorPos(buffer.curX,buffer.curY)
term.setCursorBlink(buffer.cursorBlink)
term.setTextColor(buffer.textColor)
term.setBackgroundColor(buffer.backgroundColor)
buffer.isActive=true
term.restore()
end,
}
function createRedirectBuffer(width,height,fg,bg,isColor)
bg=bg or colors.black
fg=fg or colors.white
isColor=isColor~=nil and isColor or term.isColor()
local buffer={}
for y=1,height do
local row={}
for x=1,width do
row[x]={char=" ",textColor=fg,backgroundColor=bg}
end
buffer[y]=row
end
buffer.scrX=1
buffer.scrY=1
buffer.width=width
buffer.height=height
buffer.cursorBlink=false
buffer.textColor=fg
buffer.backgroundColor=bg
buffer._isColor=isColor
buffer.curX=1
buffer.curY=1
local meta={}
local function wrap(f,o)
return function(...)
return f(o,...)
end
end
for k,v in pairs(redirectBufferBase) do
meta[k]=wrap(v,buffer)
end
setmetatable(buffer,{__index=meta})
return buffer
end
windows = {}
function drawWindows()
term.native.clear()
term.native.setCursorPos(1,1)
term.restore()
for i=1 ,#windows do
name = windows[i]
i = i+1
x = windows[i]
i = i+1
y = windows[i]
i = i+1
var = windows[i]
var.makeActive(x,y)
w = var.width
h = var.height
fromx = x-1
fromy = y-1
v = x+w
f = y+h
tox = v+1
toy = f+1
for i= fromy, toy do
paintutils.drawPixel(fromx, i, colors.blue)
paintutils.drawPixel(tox, i, colors.blue)
end
paintutils.drawLine(x, fromy, tox, toy, colors.blue)
paintutils.drawLine(fromx, fromy, tox, toy, colors.blue)
paintutils.drawPixel(fromx, fromy, colors.yellow)
paintutils.drawPixel(tox, fromy, colors.red)
ox, oy = term.getCursorPos()
term.setCursorPos(tox, fromy)
term.write("X")
term.setCursorPos(ox, oy)
end
end
function windows(name, x, y, w, h, fg, bg, isColor)
a = redirect.createRedirectBuffer(w,h,fg, bg, isColor)
table.insert(windows, name)
table.insert(windows, x)
table.insert(windows, y)
table.insert(windows, a)
drawWindows()
end
function drag()
while true do
_, button, xPos, yPos = os.pullEvent("mouse_drag")
a = tablepos+1
b = a+1
windows[a] = xPos
windows[b] = yPos
a = true
if a then break end
end
end
function drop()
evt, clic, xPos, yPos = os.pullEvent("mouse_click")
while true do
for i=1 ,#windows do
name = windows[i]
i = i+1
x = windows[i]
i = i+1
y = windows[i]
i = i+1
var = windows[i]
var.makeActive(x,y)
w = var.width
h = var.height
fromx = x-1
fromy = y-1
v = x+w
f = y+h
tox = v+1
toy = f+1
if xPos==fromx and yPos==fromy then break end
end
end
end
function detectx()
event, button, xPos, yPos = os.pullEvent("mouse_click")
for i=1 ,#windows do
name = windows[i]
i = i+1
x = windows[i]
i = i+1
y = windows[i]
i = i+1
var = windows[i]
var.makeActive(x,y)
w = var.width
h = var.height
fromx = x-1
fromy = y-1
v = x+w
f = y+h
tox = v+1
toy = f+1
if xPos==tox and yPos==fromy then
i = i-3
for a = 1, 3
table.remove (windows, i)
end
drawWindows()
end
end
end
function potatoistheonlynamethatithinkforthisfunction()
while true do
lolololololololololololololo = 0
end
end
function programrun(program)
end
goroutine.run(potatoistheonlynamethatithinkforthisfunction)
function executeprogram(program)
a = math.random(1,999)
b = math.random(1,999)
c = math.random(1,999)
spawnWithRedirect("program"..a..b..c,programrun,[b]redirect[/b],program)
end
function runshell()
a = math.random(1,999)
b = math.random(1,999)
c = math.random(1,999)
spawnWithRedirect("program"..a..b..c,programrun,[b]redirect[/b],"/rom/programs/shell")
end
function dragwindow()
term.restore()
event, button, xPos, yPos = os.pullEvent("mouse_click")
for i=1 ,#windows do
name = windows[i]
i = i+1
x = windows[i]
i = i+1
y = windows[i]
i = i+1
var = windows[i]
var.makeActive(x,y)
w = var.width
h = var.height
fromx = x-1
fromy = y-1
v = x+w
f = y+h
tox = v+1
toy = f+1
if xPos==fromx and yPos==fromy then
xdet = xPos
ydet = yPos
tablepos = i-3
parallel.waitForAny(drag, drop, detectx)
drawWindows()
end
end
end
redirect is a temp var onl for showing