ComputerCraft Archive

windont shell

pocket mining LDDestroier github

Description

A collection of all my ComputerCraft programs and the APIs they use. This is mostly just to get them the fuck off of pastebin, and also to ensure that API owners don't change things to break my precious programs...!

Installation

Copy one of these commands into your ComputerCraft terminal:

wget:wget https://raw.githubusercontent.com/LDDestroier/CC/master/windont/windont-shell.lua windont_shell
Archive:wget https://cc.shobie.xyz/cc/get/gh-LDDestroier-CC-windont-windont-shell windont_shell
Quick Install: wget https://cc.shobie.xyz/cc/get/gh-LDDestroier-CC-windont-windont-shell windont shell

Usage

Run: windont-shell

Tags

mining

Source

View Original Source

Code Preview

if not fs.exists("windont.lua") then
	print("'windont.lua' not found! Downloading...")
	local net = http.get("https://github.com/LDDestroier/CC/raw/master/windont/windont.lua")
	if net then
		local file = fs.open("windont.lua", "w")
		file.write(net.readAll())
		file.close()
		net.close()
	else
		error("Could not download Windon't.", 0)
	end
end
local windont = require "windont"

windont.default.alwaysRender = false
windont.useSetVisible = true

local scr_x, scr_y = term.getSize()
local keysDown = {}

local instances = {}
local knownNames = {
	["rom/programs/shell.lua"] = "CraftOS Shell",
	["rom/programs/edit.lua"] = "Edit",
	["rom/programs/gps.lua"] = "GPS",
	["rom/programs/list.lua"] = "List",
	["rom/programs/shutdown.lua"] = "Shutting down...",
	["rom/programs/reboot.lua"] = "Rebooting...",
	["rom/programs/monitor.lua"] = "Monitor Redirect",
	["rom/programs/emu.lua"] = "Emu (CCEmuX)",
	["rom/programs/exit.lua"] = "Goodbye!",
	["rom/programs/lua.lua"] = "Lua Interpreter",

	["rom/programs/fun/adventure.lua"] = "Adventure",
	["rom/programs/fun/worm.lua"] = "Worm",
	["rom/programs/fun/dj.lua"] = "DJ",
	["rom/programs/fun/hello.lua"] = "Hello world!",

	["rom/programs/turtle/dance.lua"] = "Dance!",
	["rom/programs/turtle/craft.lua"] = "Craft",
	["rom/programs/turtle/excavate.lua"] = "Excavate",
	["rom/programs/turtle/refuel.lua"] = "Refueling...",
	["rom/programs/turtle/go.lua"] = "Go (Turtle)",
	["rom/programs/turtle/turn.lua"] = "Turn (Turtle)",

	["rom/programs/http/pastebin.lua"] = "Pastebin",
	["rom/programs/http/wget.lua"] = "Wget",

	["rom/programs/pocket/falling.lua"] = "Falling",

	["rom/programs/rednet/chat.lua"] = "Chat",
	["rom/programs/rednet/repeat.lua"] = "Rednet Repeat",

	["rom/programs/command/exec.lua"] = "Exec (Command)",
	["rom/programs/command/commands.lua"] = "Commands",
}

-- events that can only be passed if the instance is focused
local FocusEvents = {
	["mouse_click"] = true,
	["mouse_drag"] = true,
	["mouse_up"] = true,
	["key"] = true,
	["key_up"] = true,
	["char"] = true,
	["monitor_touch"] = true,
	["paste"] = true,
	["terminate"] = true
	-- mouse_scroll is intentionally excluded
}

-- events that must have their XY values altered according to the position of the window
local CoordinateEvents = {
	["mouse_click"] = {3, 4},
	["mouse_drag"] = {3, 4},
	["mouse_up"] = {3, 4},
	["mouse_scroll"] = {3, 4}
}

local desktop = windont.newWindow(1, 1, scr_x, scr_y, {
	backColor = "9"
})
local overlay = windont.newWindow(1, 1, scr_x, scr_y, {
	backColor = "-"
})
local debugOverlay = windont.newWindow(1, 1, scr_x, scr_y, {
	backColor = "-"
})
desktop.redraw()

local instanceBoxCheck = function(i, x, y, useMain)
	assert(type(x) == "number", "x must be number")
	assert(type(y) == "number", "y must be number")
	return (
		x < 1 or x > (useMain and instances[i].mainWindow.meta.width or instances[i].termWindow.meta.width) or
		y < 1 or y > (useMain and instances[i].mainWindow.meta.height or instances[i].termWindow.meta.height)
	)
end

local focusInstance = function(i)
	if instances[i or false] then
		if i ~= 1 then
			local instance = instances[i]
			instances[1].focused = false
			table.remove(instances, i)
			table.insert(instances, 1, instance)
			instances[1].focused = true
		end
	end
end

-- checks if (x, y) is within a rectangle between (rx1, ry1), (rx2, ry2)
local rectangleCheck = function(x, y, rx1, ry1, rx2, ry2)
	return
		(x >= rx1 and x <= rx2) and
		(y >= ry1 and y <= ry2)
end

-- checks which instance should be selected if you were to click on (x, y)
local checkInstanceByPos = function(x, y, useTerm)
	for i = 1, #instances do
		if rectangleCheck(
			x,
			y,
			instances[i].mainWindow.meta.x + (useTerm and 1 or 0),
			instances[i].mainWindow.meta.y + (useTerm and 1 or 0),
			instances[i].mainWindow.meta.x + (useTerm and 1 or 0) + (useTerm and instances[i].termWindow or instances[i].mainWindow).meta.width - 1,
			instances[i].mainWindow.meta.y + (useTerm and 1 or 0) + (useTerm and instances[i].termWindow or instances[i].mainWindow).meta.height - 1
		) then
			return i
		end
	end
	return false
end

local resumeInstance = function(i, _evt, isCoordinateEvent)
	local evt = {}
	for k,v in pairs(_evt) do
		evt[k] = v
	end
	if isCoordinateEvent then
		evt[3] = evt[3] - instances[i].mainWindow.meta.x
		evt[4] = evt[4] - instances[i].mainWindow.meta.y
	end
	repeat
		if (isCoordinateEvent and instanceBoxCheck(i, evt[3], evt[4])) then
			break
		end
		oldTerm = term.redirect(instances[i].termWindow)
		success, result = coroutine.resume(instances[i].coroutine, table.unpack(evt))

		instances[i].program = shell.resolveProgram(instances[i].environment.multishell.getTitle(multishell.getCurrent()))
		instances[i].setTitle()

		term.redirect(oldTerm)
		if success and coroutine.status(instances[i].coroutine) ~= "dead" then
			instances[i].cFilter = result
		else
			instances[i].alive = false
		end
	until true
end

local newInstance = function(x, y, width, height, program, pName, addBorder)
	local output = {}
	if addBorder then
		output.mainWindow = windont.newWindow(x, y, width, height + 1, {
			baseTerm = desktop,
			alwaysRender = false,
			backColor = "7"
		})
		output.termWindow = windont.newWindow(1, 2, width, height, {
			baseTerm = output.mainWindow,
			alwaysRender = false,
			blink = false
		})
		output.oldTermPos = {1, 2, width, height}
		output.oldMainPos = {x, y, width, height + 1}
	else
		output.mainWindow = windont.newWindow(x, y, width + 2, height + 2, {
			baseTerm = desktop,
			alwaysRender = false,
			backColor = "7"
		})
		output.termWindow = windont.newWindow(2, 2, width, height, {
			baseTerm = output.mainWindow,
			alwaysRender = false,
		})
		output.oldTermPos = {2, 2, width, height}
		output.oldMainPos = {x, y, width + 2, height + 2}
	end

	local mw = output.mainWindow	-- contains the titlebar, and is the base terminal for termWindow
	local tw = output.termWindow	-- contains the program's terminal output

	tw.meta.transformation = function(x, y, char, text, back, meta)
		if x > mw.meta.width - 2 then
			return {x, y, " "}, {x, y, "-"}, {x, y, "-"}
		else
			return {x, y, char}, {x, y, text}, {x, y, back}
		end
	end

	output.refreshMainWindow = function()
		for y = 1, mw.meta.height do
			mw.setCursorPos(1, y)
			if y == 1 or y == mw.meta.height then
				mw.blit(
					(" "):rep(mw.meta.width),
					("7"):rep(mw.meta.width),
					("7"):rep(mw.meta.width)
				)
			else
				mw.blit(" ","7","7")
				mw.setCursorPos(mw.meta.width, y)
				mw.blit(" ","7","7")
			end
		end
	end
	output.refreshMainWindow()
	output.program = program or "rom/programs/shell.lua"
	output.setTitle = function()
		output.title = pName or (type(output.program) == "string" and (knownNames[fs.combine("", output.program)] or fs.getName(output.program))) or tostring(output.program)
	end
	output.setTitle()
	-- pausing will probably be implemented later
	output.paused = false
	output.timeMod = 0
	output.clockMod = 0
	output.timers = {}

	output.alive = true
	output.focused = true
	output.manipMode = 0

	output.writeTitleBar = function()
		mw.setCursorPos(1, 1)
		if output.focused then
			mw.setTextColor(colors.white)
		else
			mw.setTextColor(colors.lightGray)
		end
		mw.setBackgroundColor(colors.gray)
		mw.clearLine()

		if #output.title <= (mw.meta.width - 4) then
			mw.write(output.title)	-- write full title
		else
			mw.write(output.title:sub(1, mw.meta.width - 7) .. "...") -- draw abreviated title
		end
--		mw.setCursorPos(mw.meta.width - 3, 1)
--		mw.write(" \22\94\215")	-- minimize / maximize / close
		mw.setCursorPos(mw.meta.width - 1, 1)
		mw.write(" \215")	-- close
	end

	if type(program) == "string" then
		output.main = function()
			tw.clear()
			return shell.run(program)
		end
	elseif type(program) == "function" then
		output.main = program
	end

	output.environment = {}
	setmetatable(output.environment, {__index = _ENV})
	setfenv(output.main, output.environment)

	output.coroutine = coroutine.create(output.main)
	output.cFilter = nil

	for i = 1, #instances do
		instances[i].focused = false
	end

	table.insert(instances, 1, output)

	resumeInstance(1, {}, false)

	return output
end

local moveInstance = function(i, x, y, newWidth, newHeight, relative)
	desktop.clear()
	newWidth = math.max(newWidth or instances[i].mainWindow.meta.width, 3)
	newHeight = math.max(newHeight or instances[i].mainWindow.meta.height, 3)
	if relative then
		if x == 0 and y == 0 then
			if (not newWidth or newWidth == instances[i].mainWindow.meta.width) and (not newHeight or newHeight == instances[i].mainWindow.meta.height) then
				return
			end
		end
		instances[i].mainWindow.reposition(instances[i].mainWindow.meta.x + x, instances[i].mainWindow.meta.y + y, newWidth, newHeight)
	else
		if x == instances[i].mainWindow.meta.x and y == instances[i].mainWindow.meta.y then
			if (not newWidth or newWidth == instances[i].mainWindow.meta.width) and (not newHeight or newHeight == instances[i].mainWindow.meta.height) then
				return
			end
		end
		instances[i].mainWindow.reposition(x, y, newWidth, newHeight)
	end
	instances[i].termWindow.reposition(
		2, 2,
		math.max(instances[i].oldTermPos[3], instances[i].mainWindow.meta.width - 2),
		math.max(instances[i].oldTermPos[4], instances[i].mainWindow.meta.height - 2)
	)
	instances[i].termWindow.redraw(nil, nil, nil, {force = true})
	instances[i].refreshMainWindow()
end

local render = function()
	local wins = {}
	for i = 1, #instances do
		wins[i] = instances[i].mainWindow
		instances[i].termWindow.redraw()
	end
	windont.render({force = true}, table.unpack(wins))
	windont.render({}, debugOverlay, overlay, desktop)
end

local makeNewWindow = function(program)
	newInstance(2, 2, math.max(scr_x - 16, 8), math.max(scr_y - 6, 5), program or "rom/programs/shell.lua")
	local good = false
	while not good do
		good = true
		if #instances == 1 then
			return
		else
			for i = 2, #instances do
				if instances[1].mainWindow.meta.x == instances[i].mainWindow.meta.x and instances[1].mainWindow.meta.y == instances[i].mainWindow.meta.y then
					instances[1].mainWindow.reposition(instances[1].mainWindow.meta.x + 2, instances[1].mainWindow.meta.y + 2)
					good = false
					break
				end
			end
		end
	end
end

local cleanExit = function()
	term.setBackgroundColor(colors.black)
	term.clear()
	term.setCursorPos(1, 1)
	print("Thanks for using Windon't Shell!")
end

local main = function()

	makeNewWindow()

	local evt, success, result, oldTerm
	local cx, cy
	local isCoordinateEvent
	local usedCoordinateEvent
	local isManipulatingInstance = false
	-- handles input system
	local keyTimer = os.startTimer(0.05)

	while true do
		evt = {coroutine.yield()}
		cx, cy = term.getCursorBlink()
		if evt[1] == "key" and not evt[3] then
			keysDown[evt[2]] = 0
		elseif evt[1] == "key_up" then
			keysDown[evt[2]] = nil
		end
		if evt[1] == "term_resize" then
			scr_x, scr_y = term.getSize()
			desktop.reposition(1, 1, scr_x, scr_y)
			overlay.reposition(1, 1, scr_x, scr_y)
		end
		if evt[1] == "mouse_click" then
			focusInstance(checkInstanceByPos(evt[3], evt[4]))
			if not checkInstanceByPos(evt[3], evt[4]) then
				if evt[2] == 2 then
					makeNewWindow()
				end
			elseif evt[2] == 1 then
				if evt[4] == instances[1].mainWindow.meta.y and evt[3] == (instances[1].mainWindow.meta.x + instances[1].mainWindow.meta.width - 1) then
					instances[1].alive = false
				end
			end
		end
		if evt[1] == "terminate" and not instances[1] then
			cleanExit()
			return true
		end
		if evt[1] == "timer" and evt[2] == keyTimer then
			keyTimer = os.startTimer(0)
			for k,v in pairs(keysDown) do
				keysDown[k] = v + 0.05
			end

			if instances[1] then
				term.setCursorPos(
					instances[1].termWindow.meta.cursorX + instances[1].mainWindow.meta.x,
					instances[1].termWindow.meta.cursorY + instances[1].mainWindow.meta.y
				)
				term.setCursorBlink(instances[1].termWindow.meta.blink)
				overlay.clear()
			else
				local msg = "Right click to open shell."
				term.setCursorBlink(false)
				overlay.setCursorPos(scr_x / 2 - #msg / 2, scr_y / 2)
				overlay.write("Right click to open shell.")
			end
			render()

			-- move windows with arrow keys (for now)
			if false then
				if keysDown[keys.right] then
					desktop.clear()
					instances[1].mainWindow.reposition(instances[1].mainWindow.meta.x + 1, instances[1].mainWindow.meta.y)
				end
				if keysDown[keys.left] then
					desktop.clear()
					instances[1].mainWindow.reposition(instances[1].mainWindow.meta.x - 1, instances[1].mainWindow.meta.y)
				end
				if keysDown[keys.up] then
					desktop.clear()
					instances[1].mainWindow.reposition(instances[1].mainWindow.meta.x,     instances[1].mainWindow.meta.y - 1)
				end
				if keysDown[keys.down] then
					desktop.clear()
					instances[1].mainWindow.reposition(instances[1].mainWindow.meta.x,     instances[1].mainWindow.meta.y + 1)
				end
			end
		else
			usedCoordinateEvent = false
			isCoordinateEvent = false
			for i = 1, #instances do
				if (not isManipulatingInstance) and evt[1] == "mouse_click" and (keysDown[keys.leftAlt] or (
					(checkInstanceByPos(evt[3], evt[4], false) == i) and not (checkInstanceByPos(evt[3], evt[4], true) == i)
				)) then
					if evt[2] == 1 then
						-- dragging a window
						if instances[i].manipMode == 0 then
							instances[i].manipMode = 1
							isManipulatingInstance = true
							instances[i].dragging = {instances[i].mainWindow.meta.x - evt[3], instances[i].mainWindow.meta.y - evt[4]}
						end
					elseif evt[2] == 2 then
						-- resizing a window
						if instances[i].manipMode == 0 then
							instances[i].manipMode = 2
							isManipulatingInstance = true
							instances[i].oldTermPos = {
								instances[i].termWindow.meta.x,
								instances[i].termWindow.meta.y,
								instances[i].termWindow.meta.width,
								instances[i].termWindow.meta.height
							}
							instances[i].oldMainPos = {
								instances[i].mainWindow.meta.x,
								instances[i].mainWindow.meta.y,
								instances[i].mainWindow.meta.width,
								instances[i].mainWindow.meta.height
							}
							if evt[3] > (instances[i].mainWindow.meta.x + (instances[i].mainWindow.meta.width) - 1) - 2 then
								instances[i].resizingRight = (instances[i].mainWindow.meta.x + instances[i].mainWindow.meta.width - 1) - evt[3]
							elseif evt[3] < (instances[i].mainWindow.meta.x + 2) then
								instances[i].resizingLeft = (instances[i].mainWindow.meta.x - 1) - evt[3]
							end
							if evt[4] > (instances[i].mainWindow.meta.y + (instances[i].mainWindow.meta.height) - 1) - 2 then
								instances[i].resizingBottom = (instances[i].mainWindow.meta.y + instances[i].mainWindow.meta.height - 1) - evt[4]
							elseif evt[4] < (instances[i].mainWindow.meta.y + 2) then
								instances[i].resizingTop = (instances[i].mainWindow.meta.y - 1) - evt[4]
							end
						end
					end
				else
					if evt[1] == "mouse_up" then
						if instances[i].manipMode == 2 then
							instances[i].mainWindow.clear()
							instances[i].termWindow.reposition(2, 2, instances[i].mainWindow.meta.width - 2, instances[i].mainWindow.meta.height - 2)
							instances[i].termWindow.redraw(nil, nil, nil, {force = true})
						end
						instances[i].manipMode = 0
						isManipulatingInstance = false
						instances[i].dragging = nil
						instances[i].resizingRight = nil
						instances[i].resizingLeft = nil
						instances[i].resizingBottom = nil
						instances[i].resizingTop = nil
					elseif evt[1] == "mouse_drag" then
						if isManipulatingInstance then
							if instances[i].manipMode == 1 then
								moveInstance(
									i,
									instances[i].dragging[1] + evt[3],
									instances[i].dragging[2] + evt[4]
								)
							elseif instances[i].manipMode == 2 then
								local newX, newY = instances[i].mainWindow.meta.x, instances[i].mainWindow.meta.y
								local oriX, oriY = instances[i].mainWindow.meta.x, instances[i].mainWindow.meta.y
								local newWidth, newHeight = instances[i].mainWindow.meta.width, instances[i].mainWindow.meta.height
								local oriWidth, oriHeight = instances[i].mainWindow.meta.width, instances[i].mainWindow.meta.height
								if instances[i].resizingRight then
									newWidth = instances[i].resizingRight + (evt[3] - instances[i].oldMainPos[1] + 1)
								end
								if instances[i].resizingLeft then
									newX = instances[i].resizingLeft + evt[3] + 1
									newWidth = instances[i].oldMainPos[3] + (instances[i].oldMainPos[1] - newX)
								end
								if instances[i].resizingBottom then
									newHeight = instances[i].resizingBottom + (evt[4] - instances[i].oldMainPos[2] + 1)
								end
								if instances[i].resizingTop then
									newY = instances[i].resizingTop + evt[4] + 1
									newHeight = instances[i].oldMainPos[4] + (instances[i].oldMainPos[2] - newY)
								end
								moveInstance(
									i,
									newX,
									newY,
									newWidth,
									newHeight
								)
								if newWidth ~= oriWidth or newHeight ~= oriHeight then
									resumeInstance(i, {"term_resize"}, false)
								end
							end
						end
					end
					if (instances[i].cFilter == evt[1] or instances[i].cFilter == "terminate" or (not instances[i].cFilter)) then
						if (instances[i].focused or not FocusEvents[evt[1]]) then
							resumeInstance(i, evt, CoordinateEvents[evt[1]])
							if CoordinateEvents[evt[1]] then
								usedCoordinateEvent = true
							end
						end
					end
				end
				instances[i].writeTitleBar()
			end
		end

		-- check for dead instances
		for i = #instances, 1, -1 do
			if not instances[i].alive then
				if instances[i].focused then
					if instances[i - 1] then
						instances[i - 1].focused = true
					elseif instances[i + 1] then
						instances[i + 1].focused = true
					end
				end
				table.remove(instances, i)
				desktop.clear()
			end
		end

		-- make sure the focused window is on top
		for i = 1, #instances do
			if instances[i].focused then
				instances[i], instances[1] = instances[1], instances[i]
				break
			end
		end
	end
end

main()